1 解釋型和編譯型語言的區別
解釋是翻譯一句執行一句,更靈活,eg:python; 解釋成機器能理解的指令,而不是二進制碼
編譯是整個源程序編譯成機器可以直接執行的二進制可運行的程序,再運行這個程序 比如c++
2 簡述下 Python 中的字符串、列表、元組和字典和集合
在 Python 中,字符串、列表、元組、字典和集合是常用的數據結構,每種結構都有其獨特的特性和用途。
-
字符串 (String): ’ ’ " "
- 字符串是由字符組成的序列。在 Python 中,字符串是不可變的,這意味著一旦創建了一個字符串,就不能修改它。
- 字符串可以用單引號 (
' '
) 或雙引號 (" "
) 包圍。 - 示例:
'hello'
或"world"
-
列表 (List): [ ]
- 列表是一個有序的元素集合,元素可以是任意類型(整數、浮點數、字符串、另一個列表等)。
- 列表是可變的,可以添加、刪除或修改其中的元素。
- 列表使用方括號 (
[ ]
) 創建。 - 示例:
[1, 2, 3, 'apple', [4, 5]]
-
元組 (Tuple): ()
- 元組與列表類似,也是一個有序的元素集合,但元組是不可變的。
- 元組使用圓括號 (
( )
) 創建,但空元組可以用單獨的一個逗號創建,如t = ()
或t = ,
。 - 由于元組不可變,它們在某些情況下比列表更高效。
- 示例:
(1, 2, 3, 'banana')
-
字典 (Dictionary): {}
- 字典是一個無序的鍵值對集合。每個鍵在字典中都是唯一的,并與一個值相關聯。
- 字典使用大括號 (
{ }
) 創建,鍵和值之間用冒號 (:
) 分隔。 - 字典是可變的,可以增加、刪除或修改鍵值對。
- 示例:
{'name': 'Alice', 'age': 30}
-
集合 (Set): {}
- 集合是一個無序的、不重復的元素集合。
- 集合使用大括號 (
{ }
) 創建,但注意,空集合必須使用set()
函數創建,而不是{}
(這會創建一個空字典)。 - 集合支持數學運算,如并集、交集、差集等。
- 示例:
{1, 2, 3, 4, 5}
有序:元組 列表
唯一的:集合、字典
不可變:元組
3 簡述上述數據類型的常用方法
- 字符串:
切片:[1:3]
格式化:print(“Hello, {}! Today is {}.”.format
(“Alice”, “Monday”))
連接 a.join
(b)
替換 ‘ddd’.repalce
(‘d’,‘a’)
分割.split(',')
#用逗號分割 - 列表
切片
添加元素 .append() .extend()
刪除
del
list[0] #下標
list. pop()
# 最后一個元素
list.remove('c')
# 元素
排序 sort
反轉 reverse
- 字典
清空 .clear()
遍歷 key for key in dict
新建 .formkeys(keyname, valuves)
4 簡述 Python 中的字符串編碼
UTF-8 是隸屬于 Unicode 的可變長的編碼方式。
在 Python 中,以 Unicode 方式編碼的字符串,可以使用 encode() 方法來編碼成指定的 bytes,也可以通過 decode()方法來把 bytes編碼成字符串。
>>> "你好".encode('utf-8')
b'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
"你好"
5 一行代碼實現數值交換
a, b = b, a
6 is 和 == 的區別
is是判斷對象的id內存地址是否一致,==判斷值
可以理解為 是 和 等于
的區別
7 Python 函數中的參數類型
Python 函數的參數類型可以分為幾種,包括:
-
位置參數(Positional Arguments):
- 這些參數必須
按順序
提供,并且不能使用參數名來指定。
- 這些參數必須
-
默認參數(Default Arguments):
- 函數定義時,可以為參數指定
默認值
。如果沒有為這些參數提供值,則使用默認值。
- 函數定義時,可以為參數指定
-
關鍵字參數(Keyword Arguments):
- 這些參數在調用函數時使用
參數名
指定,這允許以任何順序傳遞參數。
- 這些參數在調用函數時使用
-
可變位置參數(Variable Positional Arguments):變的是數量
- 使用
*
表示,可以接收任意數量的位置參數,這些參數被存儲在元組中。
- 使用
-
可變關鍵字參數(Variable Keyword Arguments):
- 使用
**
表示,可以接收任意數量的關鍵字參數,這些參數被存儲在字典中。
- 使用
-
類型注解(Type Hints):
- Python 3.5+ 引入了類型注解,允許開發者指定參數預期的數據類型,但這不會對類型進行檢查,只是作為提示。
下面是一些示例來說明這些參數類型:
# 類型注解
def calculate(a: int, b: int, operator: str) -> int:if operator == '+':return a + belif operator == '-':return a - bresult = calculate(5, 3, '+')
在實際編程中,使用默認參數和可變參數可以增加函數的靈活性。關鍵字參數和類型注解則可以提高代碼的可讀性和可維護性。類型注解在現代Python開發中越來越受歡迎,尤其是在大型項目和團隊協作中,它們幫助工具和IDE進行類型檢查,從而減少錯誤。
8 *arg 和 **kwarg 作用
可變位置和可變關鍵字,只數量可變。*arg 會把位置參數轉化為 tuple,**kwarg 會把關鍵字參數轉化為 dict。
>>> def test(*arg, **kwarg):
... if arg:
... print("arg:", arg)
... if kwarg:
... print("kearg:", kwarg)
...
>>> test('ni', 'hao', key='world')
arg: ('ni', 'hao')
kearg: {'key': 'world'}
9 獲取當前時間
>>> import time
>>> import datetime
>>> print(datetime.datetime.now())
2022-09-12 19:51:24.314335
>>> print(time.strftime('%Y-%m-%d %H:%M:%S'))
2022-09-12 19:51:24
10 PEP8 規范
PEP 8 是 Python 的官方編碼風格指南,它提供了關于如何編寫清晰、可讀性強的 Python 代碼的指導。以下是 PEP 8 中一些關鍵的規范:
-
縮進:4
- 使用 4 個空格進行縮進。
-
行寬:
- 每行代碼盡量不超過 79 個字符,這樣可以在不同的設備上查看代碼時不需要水平滾動。
-
空行:2
- 在函數定義之間使用兩個空行。
- 在類定義之間也使用兩個空行,但在類的方法定義之間使用一個空行。
-
導入:1
- 每個導入應該獨占一行。
- 應該將
import
分為三部分:標準庫導入、相關第三方導入、本地應用/庫特定導入。
-
變量命名:小下劃,大是類
- 使用小寫字母和下劃線分隔的方式命名變量和函數(snake_case)。
- 使用首字母大寫的方式命名類(CamelCase)。
-
表達式和語句:
- 不要在一行內寫過多的語句。
- 避免使用復雜的表達式,盡量保持簡單。
-
編碼:
- 代碼應該默認使用 UTF-8 編碼。
-
錯誤和異常:
- 使用
raise
來引發異常,而不是raise Exception()
。
- 使用
-
代碼注釋:
- 對復雜的操作進行注釋,解釋為什么代碼要這么做。
-
類型注解:
- 從 Python 3.5 開始,可以使用類型注解來提高代碼的可讀性和健壯性。
-
函數和方法:
- 函數參數應該以單個空格分隔。
- 函數應該完成一個單一的任務。
-
命名空間:
- 避免使用全局變量。
-
布爾上下文:
- 在布爾上下文中,不要使用
if x:
這樣的語句,除非x
明顯是一個布爾值。
- 在布爾上下文中,不要使用
-
序列:
- 使用列表推導式來創建列表。
[expression for item in iterable if condition]
,其中iterable:一個可迭代對象,比如列表、元組、字典等。 even_numbers = [x for x in range(20) if x % 2 == 0] # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
squares_dict = {x: x**2 for x in range(5)} # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
- 使用列表推導式來創建列表。
-
元組:
- 單元素元組應該包含一個尾隨逗號,例如
(a,)
。
- 單元素元組應該包含一個尾隨逗號,例如
-
字典:
- 鍵值對應該使用等號
=
分隔,多個鍵值對之間用逗號分隔。
- 鍵值對應該使用等號
-
比較:
- 使用
==
來檢查對象的相等性,使用is
來檢查對象的同一性。
- 使用
-
字符串:
- 使用一致的方式表示字符串,通常是單引號
'
或雙引號"
。
- 使用一致的方式表示字符串,通常是單引號
PEP 8 只是一個指南,并不是強制的規則。但在 Python 社區中,遵循 PEP 8 可以使得代碼風格統一,提高代碼的可讀性。此外,可以使用工具如 flake8
或 pylint
來檢查代碼是否符合 PEP 8 的規范。
Python 的深淺拷貝(🧡🧡,被問到 了,一問一個不吱聲大哭)
先了解一下引用,通過一個名字來用一個對象,舉例:
a = [1,2]
,此時a就是列表[1,2]這個對象的引用。如果b = a
,b是列表[1,2]這個對象的另一個引用,當我改變a的值,b也會變。 所以,變量(名)是對象的引用,b這個新變量并沒有創建新的實例,而是指向同一個對象的新引用。
了解了引用,再來看淺拷貝。
淺拷貝:copy.copy 拷貝前后的列表只有外層獨立,內里嵌套列表還是共享的,你變他也變。對于內層只復制了元素的引用,沒有復制元素本身,兩個都指向同一個對象。而外層對象是一個新的對象,這個新的列表頂層對象包含了對子列表對象的引用,比如下面的:[1, 2, 3, [1, 2]]是新對象[1,2,3,[子列表對象的引用即1,2]]
>>> import copy
>>> list1 = [1, 2, 3, [1, 2]]
>>> list2 = copy.copy(list1)
>>> list2.append('a')
>>> list2[3].append('a')
>>> list1
[1, 2, 3, [1, 2, 'a']]
>>> list2
[1, 2, 3, [1, 2, 'a'], 'a']
深拷貝:copy.deepcopy 拷貝前后完全獨立,深深斷聯,互不相干。因為復制的是元素本身,生成的是新對象。
>>> import copy
>>> list1 = [1, 2, 3, [1, 2]]
>>> list3 = copy.deepcopy(list1)
>>> list3.append('a')
>>> list3[3].append('a')
>>> list1
[1, 2, 3, [1, 2]]
>>> list3
[1, 2, 3, [1, 2, 'a'], 'a']
深拷貝比淺拷貝更消耗資源,因為它需要創建更多的對象。
12 [lambda x:i*x for i in range(4)] 🧡🧡
首先,lambda 匿名函數,為啥用?
只有一行的函數,省去定義過程;不需要重復使用的,用完立即釋放。
其次,閉包。定義是:在內部函數里,引用了外部函數局部作用域的變量,使外層函數已經執行完畢。閉包可以訪問創建時的環境狀態。閉包函數是指當前函數用到上一層函數的局部作用域的變量時,觸發了閉包規則的函數。注意只有在內部函數被調用時才去引用外部變量,沒被調用時變量命名空間還不存在哩。
回看[lambda x:i*x for i in range(4)]
,i是外層作用域,lambda x:ix是內層函數,在構建列表推導式時,對于每一個i都創建一個ix,就是[ix,ix,ix,ix]此時i = 3,所以內部的i*x還沒開始計算,也就是lambda x內部還沒被調用,i的遞歸只是創建了4個lambda 表達式。每個 lambda 表達式中的i只是對外部變量的引用
>>> def num():
... return [lambda x:i*x for i in range(4)] #返回的是一個函數列表[3x,3x,3x,3x]
...
>>> [m(1) for m in num()] #對于函數列表中的每一個函數,賦值參數為1
[3, 3, 3, 3]
想要解決,確保了每個 lambda 表達式捕獲了 i 的一個獨立副本,變局部作用域為閉包作用域
,局部作用是執行完畢就會被銷毀,閉包作用域是外部已經執行完畢了,內部還可以訪問外部的變量的值。
>>> def num():
... return [lambda x, i = i : i*x for i in range(4)]
13 打印九九乘法表
>>> for i in range(1, 10):
... for j in range(1, i + 1):
... print(f"{i}*{j}={i * j}", end=" ")
... print()
...
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
print
函數默認是會換行的,其有一個默認參數 end
;
range左閉右開,打印一個下三角。
14 filter、map、reduce 的作用
reduce 遞歸遍歷了每個元素,返回一個值,用一行代碼解決求和、最大值、
15. 為什么不建議函數的默認參數傳入可變對象
默認參數是可變的,那調用第二次傳入的參數就是第一次調用完的結果,效果會疊加如下
def append_to_element(element, append_to=[]):element.append(append_to)return element# 第一次調用函數,預期的行為
print(append_to_element("new item")) # 輸出: ['new item']# 第二次調用函數,非預期的行為
print(append_to_element("another item")) # 輸出: ['new item', 'another item']
為了讓每次調用都相互獨立,不要用可變變量為默認參數,默認改為none,當是默認none時再創建一個[ ]
def append_to_element(element, append_to=None):if append_to is None:append_to = []element.append(append_to)return element
16. 面向對象中__new__ 和 init 區別(🧡🧡)
new是類方法,用于創建一個實例對象,對其進行內存分配。參數是cls(類名)
創建完實例對象之后,init作為實例方法,對實例對象進行初始化一些屬性和參數。參數是self(實例名)
在面向對象編程中,__new__
和 __init__
是兩個特殊的方法,它們在創建對象時有不同的用途和行為:
舉例說明:
假設我們有一個簡單的類 MyClass
:
class MyClass:def __new__(cls, *args, **kwargs):# 一般new不需要重寫,可以在這里執行一些邏輯,例如改變創建的對象類型print("Creating object with __new__")instance = super().__new__(cls) # 創建對象,保留父類的方法,避免重復return instancedef __init__(self, value):# 在這里設置對象的初始狀態print("Initializing object with __init__")self.value = value# 創建 MyClass 的實例
obj = MyClass(10)
輸出將是:
Creating object with __new__
Initializing object with __init__
在這個例子中,__new__
首先被調用并創建了 MyClass
的一個新實例。然后,__init__
被調用,設置 value
屬性。
重寫 __new__
的例子:
class BaseClass:def __new__(cls, *args, **kwargs):print("BaseClass __new__ called")return super().__new__(cls)def __init__(self, value):self.value = valueclass SubClass(BaseClass):def __new__(cls, *args, **kwargs):print("SubClass __new__ called, changing object type")instance = super().__new__(BaseClass) # 創建 BaseClass 的實例return instancedef __init__(self, value):super().__init__(value) # 初始化 BaseClass 的 __init__print(f"SubClass initialized with value: {self.value}")# 創建 SubClass 的實例
sub_obj = SubClass(20)
輸出將是:
SubClass __new__ called, changing object type
BaseClass __new__ called
SubClass initialized with value: 20
在這個例子中,我們重寫了 SubClass
的 __new__
方法,使其創建了 BaseClass
的實例而不是 SubClass
的實例。這演示了 __new__
方法如何控制對象的創建過程。
通常,__new__
方法在大多數情況下不需要重寫,除非你有特殊的對象創建邏輯。而 __init__
方法則更常用于初始化對象的狀態。
17. 三元運算規則
執行1 if 條件 else 執行2
>>> >>> a, b = 1, 2
>>> h = a - b if a > b else a + b
>>> h
3
18. 生成隨機數
用np.random也可以!
>>> import random
>>> random.random()
0.7571910055209727
>>> random.randint(1, 100)
23
>>> random.uniform(1, 5) #random.uniform(a, b) 返回一個隨機浮點數 N,使得 a <= N < b
3.0640732831151687
19. zip 函數用法
zip() 函數將可迭代的對象作為參數,將對象中對應的元素打包成一個元組,然后返回由這些元組組成的列表。
一對一打包成元組
>>> list1 = ['zhangfei', 'guanyu', 'liubei', 'zhaoyun']
>>> list2 = [0, 3, 2, 4]
>>> list(zip(list1, list2))
[('zhangfei', 0), ('guanyu', 3), ('liubei', 2), ('zhaoyun', 4)]
20. range和xrange的區別
只有Python2中才有xrange()和range(),Python3中的range()其實就是Python2中xrange()。即都用range
21. with方法打開文件的作用
打開文件在進行讀寫的時候可能會出現一些異常狀況,如果按照常規的f.open()寫法,我們需要 try,except,finally,做異常判斷,并且文件最終不管遇到什么情況,都要執行f.close() 關閉文件,with方法幫我們實現了finally 中 f.close()。
所以,能在代碼執行完畢后,資源能夠被正確地關閉或釋放,即使在代碼執行過程中發生異常也是如此。
with open("hello.txt", "a") as f:f.write("hello world!")
總結:文件會遇到異常,也都需要關閉,用with打開不論是否遇到異常,都能正確關閉。
22. 字符串轉列表 s.split(‘,’)
>>> s = "1,2,3,4,5,6,7,8,9"
>>> s.split(",")
['1', '2', '3', '4', '5', '6', '7', '8', '9']
字符串split返回列表
23. 字符串轉整數
list(map(lambda x: int(x), s.split(",")))
先轉為列表,再用map遍歷轉int
24.刪除列表中的重復值
先變成set集合再list,變過去再變回來,集合去重 list(set(mylist))
25. 字符串單詞統計
統計字母個數用collection的counter
>>> from collections import Counter
>>> mystr = 'sdfsfsfsdfsd,were,hrhrgege.sdfwe!sfsdfs'
>>> Counter(mystr)
Counter({'s': 9,'d': 5,'f': 7,',': 2,'w': 2,'e': 5,'r': 3,'h': 2,'g': 2,'.': 1,'!': 1})
統計單詞個數,先變為列表,在計算列表長度
>>> mystr2 = "hello, Nice to meet you!"
>>> len(mystr2.split(" "))
5
26. 列表推導,求奇偶數
[x for x in range(20) if x % 2 == 1]
27. 一行代碼展開列表
對于list1中的每個元素i(子列表),遍歷其所有元素j,并將這些元素收集到一個新的列表中:list1 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[ j for i in list1 for j in i]
28. 實現二分法查找函數
//向下取整到最接近的整數
非遞歸
def binary_search(data, item):left = 0right = len(data) - 1while left <= right:mid = (left + right) // 2if data[mid] == item:return Trueelif data[mid] < item:left = mid + 1else:right = mid - 1return False
遞歸
def binary_search(data, item):n = len(data)if n > 0:mid = n // 2if data[mid] == item:return Trueelif data[mid] > item:return binary_search(data[:mid], item)else:return binary_search(data[mid + 1:], item)return False
不管怎樣,都是返回等于,更新是中間值-1和中間值+1
29. 合并兩個元組到字典(zip一對一打包)
先zip再dict
>>> a = ("zhangfei", "guanyu")
>>> b = (66, 80)
>>> dict(zip(a, b)) ##
{'zhangfei': 66, 'guanyu': 80}
30. 給出如下代碼的輸入,并簡單解釋
>>> a = (1, 2, 3, [4, 5, 6, 7], 8)
>>> a[3] = 2
?:()是元組,元組不能修改,不可變
>>> a = (1, 2, 3, [4, 5, 6, 7], 8)
>>> a[3][2] = 2
>>> a
(1, 2, 3, [4, 5, 2, 7], 8)
?:列表可修改,就()元組不行
32. 列表推導式[]、字典推導式{}和生成器表達式()
列表推導式是方括號[],返回一個列表list [ k for k in range(10)]
字典推導式是花括號還有鍵和值,返回一個字典dic
>>> dic = {k: 2 for k in ["a", "b", "c", "d"]}
>>> dic
{'a': 2, 'b': 2, 'c': 2, 'd': 2}
>>> type(dic)
dict
生成器是圓括號(),用next訪問元素
ge = (i for i in range(20))
>>> ge_list
<generator object <genexpr> at 0x000001C3C127AAC8> #由一個生成器表達式(<genexpr>)創建,并存儲在內存地址0x000001C3C127AAC8處
next(ge)
33. 簡述 read、readline、readlines 的區別
read() 讀取整個文件
readline() 讀取下一行,使用生成器方法
readlines() 讀取整個文件到一個迭代器,需要一行一行遍歷才能輸出
# 假設有一個名為 'example.txt' 的文件,內容如下:
# Line 1
# Line 2
# Line 3with open('example.txt', 'r') as file:# 使用 read() 方法讀取整個文件content = file.read()print(content)# 重置文件指針到開始位置file.seek(0)# 使用 readline() 方法逐行讀取print(file.readline()) # 輸出: 'Line 1\n'print(file.readline()) # 輸出: 'Line 2\n'# 再次重置文件指針到開始位置file.seek(0)# 使用 readlines() 方法讀取所有行lines = file.readlines()for line in lines:print(repr(line)) # 輸出: 'Line 1\n', 'Line 2\n', 'Line 3\n'
34. 打亂一個列表 andom.shuffle
>>> import random
>>> list = list(range(1, 10))
>>> random.shuffle(list)
>>> list
[3, 9, 1, 4, 6, 2, 8, 7, 5]
35. 反轉字符串
‘luobodazahui’[::-1]表示以-1的步長向前遍歷,相當于從后往前遍歷一遍,也就是反轉。而列表可以直接用reverse
36. 單下劃線和雙下劃線的作用
37. 新式類和舊式類
在 python 里凡是繼承了 object的類,都是新式類
Python3 里只有新式類
(又是一個版本的問題)
38. Python 面向對象中的繼承有什么特點
繼承是一種創建新類的方式,在 Python 的面向對象編程中,繼承具有以下特點:
-
基類(父類)與子類(子類):在繼承關系中,被繼承的類稱為基類或父類,繼承基類的類稱為子類。子類會繼承基類的屬性和方法。
-
屬性與方法繼承:子類會繼承基類的所有屬性和方法,因此在子類中可以訪問基類的屬性和方法。根據繼承方式的不同(如單繼承、多重繼承),子類可以繼承多個基類的屬性和方法。
-
擴展與覆蓋:子類可以在繼承基類的基礎上進行擴展,添加新的屬性和方法。同時,子類也可以覆蓋(重寫)基類的方法以實現不同的功能。當子類中定義了與基類同名的方法時,子類會優先調用自己的方法。
-
super()
函數:在子類中,可以使用super()
函數來調用基類的方法。這在子類需要在重寫方法的基礎上擴展基類功能時非常有用。使用super()
函數可以確保基類的方法按照方法解析順序(MRO)正確地調用。 -
方法解析順序(MRO):Python 中使用 C3 線性化算法來解決多重繼承的順序問題。MRO 是一個包含類自身及其所有基類的有序列表,它決定了類繼承體系中調用方法的順序。可以使用
ClassName.mro()
或super()
函數查看 MRO 列表。 -
抽象基類(ABC):Python 中的抽象基類用于定義接口規范,它強制子類實現特定的方法。抽象基類可以通過
abc
模塊的ABCMeta
元類和abstractmethod
裝飾器來實現。
下面是一個簡單的繼承示例:
class Animal:def __init__(self, name):self.name = namedef speak(self):passclass Dog(Animal):def speak(self):return f'{self.name} says Woof!'class Cat(Animal):def speak(self):return f'{self.name} says Meow!'animals = [Dog("Max"), Cat("Molly")]for animal in animals:print(animal.speak())
在這個示例中,Dog
和 Cat
類都繼承了 Animal
類,并分別覆蓋了 speak()
方法。
39. super 函數的作用
用于調用父類(超類)的方法或初始化父類(在__init__中)
class Parent:def __init__(self, value):self.value = valuedef show(self):print(f"Parent value: {self.value}")class Child(Parent):def __init__(self, value, extension):super().__init__(value) # 初始化父類的 __init__self.extension = extensiondef show(self):super().show() # 調用父類的 show 方法print(f"Child extension: {self.extension}")# 創建 Child 類的實例
child = Child(10, 'extra info')
child.show()
40. 類中的各種方法
在類中,我們可以定義各種不同類型的函數,主要包括以下幾種:
- 實例方法:這是類中最常見的函數類型,它們需要通過實例來調用,第一個參數默認為
self
,代表實例本身,可以訪問和修改實例的屬性。
class MyClass:def instance_method(self, a, b):return a + b
- 類方法:類方法是定義在類上的函數,通過
@classmethod
裝飾器來修飾,它們的第一個參數默認為cls
,代表類本身,可以訪問和修改類屬性,但不能訪問實例屬性。
class MyClass:class_variable = 123@classmethoddef class_method(cls):cls.class_variable += 1return cls.class_variable
- 靜態方法:靜態方法是定義在類上的函數,通過
@staticmethod
裝飾器來修飾,它們不需要特定的第一個參數,不能訪問類或實例的任何屬性。
class MyClass:@staticmethoddef static_method(a, b):return a * b
- 屬性方法:屬性方法可以讓類的一個方法變成只讀屬性,或者為屬性的讀寫提供特定的方法。通過
@property
裝飾器實現。
class MyClass:def __init__(self, value):self._value = value@propertydef value(self):return self._value@value.setterdef value(self, new_value):if isinstance(new_value, int):self._value = new_valueelse:raise ValueError("Value must be an integer")
- 魔法方法:這些方法以雙下劃線開頭和結尾,由 Python 自動調用,用于實現類的內部機制。比如
__init__
,__del__
,__str__
,__eq__
等。
class MyClass:def __init__(self, value):self.value = valuedef __str__(self):return f"MyClass with value {self.value}"def __eq__(self, other):if isinstance(other, MyClass):return self.value == other.valuereturn False
以上就是類中常見的幾種函數類型。
41. 如何判斷是函數還是方法
與類和實例無綁定關系
的 function都屬于函數(function)
與類和實例有綁定關系
的 function都屬于方法(method)
42. isinstance 的作用以及與type()的區別(🧡🧡)
區別:
type()不會認為子類是一種父類類型,不考慮繼承關系
;
isinstance()會認為子類是一種父類類型,考慮繼承關系
。
class A(object):passclass B(A):pass>>> a = A()
>>> b = B()>>> print(isinstance(a, A))
True
>>> print(type(a) == A)
True>>> print(isinstance(b, A)) #考慮繼承
True
>>> print(type(b) == A) #不考慮繼承
False
43. 單例模式與工廠模式
單例模式和工廠模式是兩種常用的軟件設計模式,它們在軟件設計中扮演著不同的角色,具有各自的特點和適用場景。以下是兩種模式的詳細介紹:
單例模式
- 定義:單例模式是一種設計模式,它確保一個類只有一個實例,并提供一個全局訪問點來訪問該實例。
- 特點:
- 唯一性:單例模式保證一個類在整個應用程序中只有一個實例。
- 全局訪問點:通過單例模式,可以提供一個全局訪問點來訪問該類的唯一實例。
- 適用場景:適用于創建一個對象需要消耗過多資源,或者需要保證對象唯一性的場景,如數據庫連接池、線程池等。
- 實現方式:單例模式有多種實現方式,包括懶漢式、餓漢式、雙重檢查鎖和登記式等。
工廠模式
- 定義:工廠模式是一種設計模式,它通過一個工廠類來封裝和抽象對象的創建過程,使得客戶端代碼不需要直接進行對象的實例化。
- 特點:
- 封裝性:工廠模式封裝了對象創建的細節,降低了系統各部分之間的耦合度。
- 接口一致性:所有創建的對象通常都實現自同一個接口或繼承自同一個基類,增加了代碼的靈活性。
- 適用場景:適用于需要生成復雜對象,或者需要靈活應對不同條件創建不同實例的場景,如數據庫訪問、日志記錄等。
- 實現方式:工廠模式有多種實現方式,包括簡單工廠模式、工廠方法模式和抽象工廠模式。
區別
- 目的:單例模式主要用于控制類的實例數量,確保只有一個實例;而工廠模式主要用于封裝對象的創建過程,提高代碼的可維護性和可擴展性。
- 實現方式:單例模式通過類的靜態方法和私有構造函數來實現;工廠模式通過工廠類來創建對象實例。
- 適用場景:單例模式適用于需要保證對象唯一性的場景;工廠模式適用于需要靈活創建不同對象實例的場景。
通過以上分析,我們可以看到單例模式和工廠模式在設計模式中各有其獨特的用途和優勢,選擇哪種模式取決于具體的應用場景和需求。
44. 查看目錄下的所有文件
import os
print(os.listdir('.')) # 其中 '.' 表示當前工作目錄。這個函數會返回一個列表,包含了當前目錄下所有的文件和目錄名。
45. 計算由1到5組成的互不重復的三位數
for i in range(1,6):for j in range(1,6):for k in range(1,6):if i != j and j != k and k !=i:print(f"{i}{j}{k}")
46. 去除字符串首尾空格
.strip(刪除字符串兩端的空白字符或者指定字符
>>> " hello world ".strip()
'hello world'
47. 去除字符串中間的空格
>>> "hello you are good".replace(" ", "")
'helloyouaregood'
>>> "".join("hello you are good".split(" "))
'helloyouaregood'
48. 字符串格式化方式
方法一:使用 %
操作符
print(“This is for %s” % “Python”)
print(“This is for %s, and %s” %(“Python”, “You”))
方法二:str.format
(在 Python3 中,引入了這個新的字符串格式化方法)
print(“This is my {}”.format(“chat”))
print(“This is {name}, hope you can {do}”.format(name=“zhouluob”, do=“like”))
方法三:f-strings
(在 Python3-6 中,引入了這個新的字符串格式化方法)
name = “luobodazahui”
print(f"hello {name}")
49. 將"hello world"轉換為首字母大寫"Hello World"
1 對字符串.title()
函數 str1 = “hello world”
str1.title()
2 .對單詞capitalize()函數
" ".join(list(map(lambda x: x.capitalize(), str1.split(" "))))
3 對字符.upper()
" ".join(list(map(lambda x: x[0].upper() + x[1:], str1.split(" "))))
map()函數將這個函數應用到分割后的單詞列表的每個元素上
50. 一行代碼轉換列表中的整數為字符串
>>> list1 = [1, 2, 3]
>>> list(map(lambda x: str(x) for x in list1))# 或者 [lambda x: str(x) for x in list1]列表推導式
['1', '2', '3']
51. Python 中的反射(🧡🧡)27號
基于字符串的事件驅動!利用字符串的形式對模塊的內存進行修改
getattr,hasattr,setattr,delattr 對模塊的修改都在內存中進行,并不會影響文件中真實內容。
52. metaclass 元類(🧡🧡)
type就是創建object類對象的類,obeject是type的實例,創建一個類其實是type的__call__運算符的重載
正常的 MyClass 定義,和手工去調用type運算符的結果是一樣的
class X:a = 1X = type('X', (object,), dict(a=1))
那元類是干嘛的呢?
是type的子類,通過替換type中的__call__運算符重載機制,可以實現父類對子類的屬性進行操作。
class MyMeta(type):def __new__(cls, *args, **kwargs):print('===>MyMeta.__new__')print(cls.__name__)return super().__new__(cls, *args, **kwargs)def __init__(self, classname, superclasses, attributedict):super().__init__(classname, superclasses, attributedict)print('===>MyMeta.__init__')print(self.__name__)print(attributedict)print(self.tag)def __call__(self, *args, **kwargs):print('===>MyMeta.__call__')obj = self.__new__(self, *args, **kwargs)self.__init__(self, *args, **kwargs)return objclass Foo(object, metaclass=MyMeta):tag = '!Foo'def __new__(cls, *args, **kwargs):print('===>Foo.__new__')return super().__new__(cls)def __init__(self, name):print('===>Foo.__init__')self.name = name
# ----------------------輸出----------------------
# ===>MyMeta.__new__
# MyMeta
# ===>MyMeta.__init__
# Foo
# {'__module__': '__main__', '__qualname__': 'Foo', 'tag': '!Foo', '__new__': <function Foo.__new__ at 0x000001B1B2379678>, '__init__': <function Foo.__init__ at 0x000001B1B2379708>, '__classcell__': <cell at 0x000001B1B23880A8: MyMeta object at 0x000001B1B1A509A8>}
# !Foo>>> print('test start')
>>> foo = Foo('test')
>>> print('test end')
# test start
# ===>MyMeta.__call__
# ===>Foo.__new__
# ===>Foo.__init__
# test end
創建一個類時,(1)先在屬性中查找是否有metaclass屬性,(2)沒有,就在父類中查找(3)沒有就在模塊中查找(4)再沒有,就用type來創建對象。
注意,通過metaclass,必須返回一個類return obj
同時,可以實現在創建時,就對子類的屬性進行操作。(一般父類是不可以對子類的屬性操作的哦)
def MyMetaFunction(classname, superclasses, attributedict):attributedict['year'] = 2019return type(classname, superclasses, attributedict)class Foo(object, metaclass=MyMetaFunction):tag = '!Foo'def __new__(cls, *args, **kwargs):print('===>Foo.__new__')return super().__new__(cls)def __init__(self, name):print('===>Foo.__init__')self.name = name>>> foo = Foo('test')
===>Foo.__new__
===>Foo.__init__
>>> print('name:%s,tag:%s,year:%s' % (foo.name, foo.tag, foo.year))
name:test,tag:!Foo,year:2019
先有元類,再有類,再有實例。
53. sort 和 sorted 的區別
sort改變原列表。sorted返回一個新的對象
54. Python 中的 GIL
GIL 是 Python 的全局解釋器鎖,同一進程中假如有多個線程運行,一個線程在運行 Python 程序的時候會占用 Python 解釋器(加了一把鎖即 GIL),使該進程內的其他線程無法運行,等該線程運行完后其他線程才能運行。如果線程運行過程中遇到耗時操作,則解釋器鎖解開,使其他線程運行。所以在多線程中,線程的運行仍是有先后順序的,并不是同時進行。
進程(Process)
- 定義:進程是操作系統進行資源分配和調度的一個獨立單位。它是應用程序運行的實例,擁有獨立的內存空間。
- 地址空間:每個進程有自己的地址空間,這包括代碼段、數據段和堆棧等。
- 全局數據:進程擁有自己的全局變量和靜態變量。
- 獨立性:進程之間相互獨立,一個進程的崩潰不會直接影響到其他進程。
- 資源占用:進程間通信(IPC)和進程切換開銷較大,因為它們需要操作系統進行協調。
- 創建和銷毀開銷:進程的創建和銷毀需要較多的資源和時間。
線程(Thread)
- 定義:線程是進程中的一個實體,是CPU調度和執行的單位,是程序執行的最小單位。
- 地址空間:同一進程內的線程共享進程的地址空間,包括代碼段和數據段。
- 全局數據:線程共享相同的全局變量和靜態變量。
- 輕量級:線程的創建、同步和銷毀的開銷比進程小。
- 并發性:線程使得多任務并發執行成為可能,它們可以并行處理任務。
- 資源共享:線程之間可以輕松共享數據,但這也可能導致數據同步問題。
進程與線程的區別:
- 資源占用:進程擁有獨立的資源,線程共享進程的資源。
- 執行:進程是程序的執行流程,線程是進程中執行的子流程。
- 創建開銷:進程的創建和銷毀開銷較大,線程相對較小。
- 通信:進程間通信需要使用IPC機制,線程間可以直接訪問共享內存。
- 獨立性:進程間獨立,線程間共享。
- 錯誤影響:進程的一個錯誤通常不會影響其他進程,但線程的錯誤可能影響整個進程。
- 上下文切換:線程間的上下文切換比進程快,因為它們共享同樣的內存空間。
理解示例:
- 進程可以比作一個工廠,每個工廠擁有自己的資源和生產流程。
- 線程可以比作工廠中的工人,他們共享工廠的資源,協同工作以完成生產任務。
55. 產生8位隨機密碼(🧡🧡)
random.choice選擇,string.printable生成字符串
>>> import random
>>> import string
>>> "".join(random.choice(string.printable[:-7]) for i in range(8)) # 從 string.printable 中移除最后 7 個字符
生成器表達式和列表推導式(list comprehension)都是簡潔地創建新數據結構的方法,但它們之間存在一些關鍵區別:
內存使用:列表推導式會立即生成一個新的列表,這意味著它會占用與列表大小成正比的內存。對于大型數據集,這可能導致內存不足。而生成器表達式不會立即生成值,而是返回一個生成器對象。這個對象在迭代過程中逐個產生值,因此它的內存占用很小,無論它表示的序列有多大。
語法:生成器表達式的語法與列表推導式非常相似,只是在圓括號而不是方括號內編寫。例如:
- 列表推導式:
[expr for item in iterable if condition]
- 生成器表達式:
(expr for item in iterable if condition)
返回類型:列表推導式返回一個列表,而生成器表達式返回一個生成器對象(
generator
類型)。生成器對象實現了迭代器協議,可以使用next()
函數或for
循環進行迭代。可迭代性:生成器表達式返回的生成器對象只能迭代一次。當所有值都被迭代完后,生成器對象就會耗盡。要再次迭代,需要重新創建一個新的生成器對象。而列表推導式返回的列表可以多次迭代。
以下是一個簡單的例子,展示了列表推導式和生成器表達式的用法:
# 列表推導式 squares = [random.randint(1, 100) ** 2 for _ in range(5)] print(squares)# 生成器表達式 squares_gen = (random.randint(1, 100) ** 2 for _ in range(5)) for square in squares_gen:print(square, end=" ") ```
56. 輸出原始字符
>>> print('hello\nworld')
hello
world
>>> print(b'hello\nworld')
b'hello\nworld'
>>> print(r'hello\nworld')
hello\nworld
b 前綴表示字節字符串(byte string),即 b’hello\nworld’ 是一個包含字節的不可變序列。這種字符串用于處理二進制數據。
r 前綴表示原始字符串(raw string),在這種字符串中,轉義字符不會被處理。
57. 簡述 any() 和 all() 方法
all 可迭代對象中的所有元素是否都為 True
any 函數用于判斷可迭代對象中是否至少有一個元素為 True
0 none false都是false
58. 反轉整數
是否是整數,是否一位數,是否負數
def reverse_int(x):if not isinstance(x, int):return Falseif -10 < x < 10:return xtmp = str(x)if tmp[0] != '-':tmp = tmp[::-1]return int(tmp)else:tmp = tmp[1:][::-1]x = int(tmp)return -x
59. 函數式編程(🧡🧡)
函數式編程是一種抽象程度很高的編程范式,純粹的函數式編程語言編寫的函數沒有變量,因此,任意一個函數,只要輸入是確定的,輸出就是確定的,這種純函數稱之為沒有副作用。而允許使用變量的程序設計語言,由于函數內部的變量狀態不確定,同樣的輸入,可能得到不同的輸出,因此,這種函數是有副作用的。由于 Python 允許使用變量,因此,Python 不是純函數式編程語言。
函數式編程允許參數是函數,也允許返回一個函數
60. 簡述閉包(🧡🧡)
如果在一個內部函數里,對在外部作用域(但不是在全局作用域)的變量進行引用,那么內部函數就被認為是閉包(closure)。允許函數“記住”其被創建時的環境狀態,即使外層函數已經執行完畢
閉包特點:
必須有一個內嵌函數;
內嵌函數必須引用外部函數中的變量;
外部函數的返回值必須是內嵌函數。
閉包的應用場景: 柯里化(Currying):將一個多參數的函數轉換成多個單參數函數。 數據隱藏:通過閉包實現封裝和數據隱藏。
裝飾器:Python中的裝飾器就是一個典型的閉包應用。 迭代器和生成器:迭代器和生成器的 next 方法經常使用閉包來保持迭代狀態。
61. 簡述裝飾器(🧡🧡)
裝飾器是一個嵌套函數,不需要修改被裝飾函數的源代碼,用于給被裝飾的函數修改或添加功能,內部的wrapper函數替代原始函數。
被裝飾函數作為參數傳入裝飾器,內部函數替代原始函數執行后還可以添加一些功能。
廣泛應用于緩存、權限校驗(如django中的@login_required和@permission_required裝飾器)、性能測試(比如統計一段程序的運行時間)和插入日志等應用場景
基本用法:
-
定義裝飾器:
- 創建一個裝飾器函數,通常接受一個函數作為參數。
-
包裝函數:
- 在裝飾器內部,定義一個包裝函數(通常命名為
wrapper
),它將被返回以替代原始函數。
- 在裝飾器內部,定義一個包裝函數(通常命名為
-
調用原始函數:
- 在包裝函數中,你可以添加額外的邏輯,然后調用原始函數。
-
返回包裝函數:
- 裝飾器返回包裝函數,這樣當原始函數被調用時,實際上是調用了包裝函數。
示例:
def my_decorator(func):def wrapper():print("Something is happening before the function is called.")func()print("Something is happening after the function is called.")return wrapper@my_decorator
def say_hello():print("Hello!")say_hello()
輸出:
Something is happening before the function is called.
Hello!
Something is happening after the function is called.
在這個例子中,my_decorator
是一個裝飾器,它接受一個函數 func
作為參數,并返回一個新的函數 wrapper
。say_hello
函數被 @my_decorator
裝飾,這意味著 say_hello
函數被 my_decorator
包裝。
帶參數的裝飾器:
裝飾器也可以接受參數。為了實現這一點,你可以在裝飾器外層再定義一個函數,該函數接受參數并返回實際的裝飾器。
def repeat(num_times):def decorator(func):def wrapper(*args, **kwargs):for _ in range(num_times):result = func(*args, **kwargs)return resultreturn wrapperreturn decorator@repeat(num_times=3)
def greet(name):print(f"Hello, {name}!")greet("World")
輸出:
Hello, World!
Hello, World!
Hello, World!
在這個例子中,repeat
函數接受一個參數 num_times
,然后返回一個裝飾器 decorator
,該裝飾器接受一個函數并返回一個新的包裝函數 wrapper
。
裝飾器的用途:
- 日志記錄:在函數執行前后添加日志記錄。
- 性能測試:測量函數執行時間。
- 事務處理:確保數據庫事務的一致性。
- 權限檢查:在執行函數前檢查用戶權限。
- 緩存:緩存函數的結果以提高性能。
62. 協程的優點
63. 實現斐波那契數列
64. 正則切分字符串
items = re.split(pattern, text)
正則表達式(Regular Expression,簡稱regex)是一種強大的文本處理工具,用于搜索、替換、切分或匹配字符串中的模式。在Python中,正則表達式通過內置的re
模塊提供支持。
使用正則表達式切分字符串的基本步驟:
-
導入
re
模塊:import re
-
編寫正則表達式:
- 正則表達式是一個字符串,包含了用于定義搜索模式的字符和特殊符號。
-
使用
re.split()
方法:re.split(pattern, string)
:使用正則表達式pattern
來切分字符串string
。
-
獲取結果:
re.split()
返回一個列表,其中包含了被正則表達式定義的模式切分后的子字符串。
示例:
假設我們有一個字符串,包含了用逗號分隔的數值,我們想要將這些數值單獨切分出來:
import retext = "apple,101,banana,202,cherry,303"
# 正則表達式:非數字字符(,)
pattern = r'[^\d]+'# 使用正則表達式切分字符串
items = re.split(pattern, text)
print(items) # 輸出: ['apple', '101', 'banana', '202', 'cherry', '303']
在這個例子中,[^\d]+
是一個正則表達式,表示匹配一個或多個非數字字符。re.split()
使用這個模式來切分字符串text
。
注意事項:
- 正則表達式需要根據具體需求來編寫,不同的模式會有不同的切分效果。
- 特殊字符(如
*
、.
、?
、[ ]
、( )
等)在正則表達式中有特殊含義,如果需要匹配這些字符本身,通常需要使用反斜杠\
進行轉義。 - 使用正則表達式時,要注意其性能,復雜的正則表達式可能會影響程序的執行效率。
正則表達式是一種非常靈活和強大的文本處理工具,掌握它可以大大提高處理字符串的效率。
65. yield 用法
67. 冒泡排序
68. 快速排序
快速排序(Quick Sort)是一種高效的排序算法,由英國計算機科學家 Tony Hoare 于 1960 年代提出
快速排序的工作原理如下:
- 選擇一個基準元素(pivot),可以是列表的任意元素。通常選擇列表的第一個元素、最后一個元素或中間元素作為基準。
- 將列表中小于基準元素的值移動到基準的左側;將大于基準元素的值移動到基準的右側。這個過程稱為分區(partitioning)操作。經過分區后,基準元素將位于其最終排序位置。
- 對基準元素左側和右側的子列表進行遞歸處理,分別選擇左側子列表和右側子列表的基準元素并進行分區。
- 遞歸終止條件是處理的子列表只有一個元素或為空。
以下是一個使用 Python 實現的快速排序示例:
def quick_sort(arr):if len(arr) <= 1:return arrpivot = arr[len(arr) // 2]left = [x for x in arr if x< pivot]middle = [x for x in arr if x == pivot]right = [x for x in arr if x > pivot]return quick_sort(left) + middle + quick_sort(right)# 示例
arr = [64, 34, 25, 12, 22, 11, 90]
sorted_arr = quick_sort(arr)
print("Sorted array is:", sorted_arr)
輸出結果:
Sorted array is: [11, 12, 22, 25, 34, 64, 90]
快速排序的平均時間復雜度為 O(nlog(n)),最壞情況下的時間復雜度為 O(n^2)。但在實際應用中,快速排序通常比其他 O(nlog(n)) 算法更高效,因為它的內部循環可以在大部分架構上更有效地利用緩存。為了避免最壞情況的發生,可以使用隨機方法選擇基準元素。
70. requests 簡介
71. 比較兩個 json 數據是否相等
72. 讀取鍵盤輸入 input()
def forinput():input_text = input()print("your input text is: ", input_text)>>> forinput()
>? 2
your input text is: 2
73. enumerate()的用法
74. pass 語句
占位,不做操作,為了保持結構完整性
def forpass(n):if n == 1:passelse:print('not 1')>>> forpass(1)
75. 正則匹配郵箱
76. 統計字符串中大寫字母的數量
·if i.isupper()
77. json 序列化時保留中文
ensure_ascii=False
78. 簡述繼承
79. 什么是猴子補丁(🧡🧡)
猴子補丁(Monkey Patch)和裝飾器(Decorator)都是 Python 中用于修改或增強已有對象功能的技術,但它們的用途、實現方式以及適用場景有所不同
猴子補丁(Monkey Patch):
猴子補丁是在運行時動態地修改類或模塊的行為。通過直接修改類或模塊的屬性,可以添加、修改或刪除現有的方法、屬性等。猴子補丁的主要優點是可以在不修改原始代碼的情況下調整行為,這在調試、測試和擴展第三方庫時非常有用。然而,猴子補丁可能導致代碼難以維護和理解,因為它改變了對象的內部實現。另外,使用猴子補丁時需要謹慎,因為在某些情況下,它可能導致意外的副作用或不可預見的錯誤。
以下是一個猴子補丁的示例,用于修改字符串類的 upper
方法:
def custom_upper(self):return self[::-1].upper()str.upper = custom_uppertext = "hello"
print(text.upper()) # 輸出 "OLLEh"
裝飾器(Decorator):
裝飾器是一種設計模式,用于在不修改原始函數或類的基礎上,為其添加新功能或者修改現有功能。裝飾器本質上是一個接受函數或類作為參數的高階函數,它返回一個新的函數或類,以實現對輸入對象功能的擴展或修改。裝飾器語法使用 @decorator_name
語法糖,并放在要修飾的函數或類定義之前。
以下是一個使用裝飾器記錄函數執行時間的示例:
import timedef timer_decorator(func):def wrapper(*args, **kwargs):start_time = time.time()result = func(*args, **kwargs)end_time = time.time()print(f"{func.__name__} took {end_time - start_time:.2f} seconds to execute.")return resultreturn wrapper@timer_decorator
def some_function():time.sleep(1)some_function()
總結:
- 猴子補丁是在運行時動態修改對象的行為,而裝飾器是通過高階函數在編譯時修改或增強對象的功能。
- 猴子補丁主要適用于對模塊或類的內部實現進行修改,而裝飾器主要用于修改或增強函數或類的功能,而不改變其內部實現。
- 裝飾器提供了更好的封裝、可維護性和可讀性,而猴子補丁可能導致代碼變得難以理解和維護。
- 盡量使用裝飾器來實現功能擴展,而避免使用猴子補丁,除非確實需要在運行時修改對象的行為。
80. help() 函數和 dir() 函數
81. 解釋 Python 中的//,%和**運算符
82. 主動拋出異常
raise
def test_raise(n):if not isinstance(n, int):raise Exception("not a int type")else:print("good")>>> test_raise(8.9)
Traceback (most recent call last):File "D:\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 3331, in run_codeexec(code_obj, self.user_global_ns, self.user_ns)File "<ipython-input-106-27962090d274>", line 1, in <module>test_raise(8.9)File "<ipython-input-105-8095f403c7e2>", line 3, in test_raiseraise Exception("not a int type")
Exception: not a int type
83. tuple 和 list 轉換
tuple () list()
>>> tuple1 = (1, 2, 3, 4)
>>> list1 = list(tuple1)
>>> print(list1)
>>> tuple2 = tuple(list1)
>>> print(tuple2)
84. 簡述斷言
Python 的斷言就是檢測一個條件,如果條件為真,它什么都不做;反之它觸發一個帶可選錯誤信息的 AssertionError。
85. 什么是異步非阻塞
86. 什么是負索引
87. 退出 Python 后,內存是否全部釋放
88. Flask 和 Django 的異同
89. 創建刪除操作系統上的文件
90. 簡述 logging 模塊
91. 統計字符串中字符出現次數
92. 正則 re.complie 的作用
93. try except else / finally 的意義
94. 反轉列表
95. 字符串中數字替換
>>> import re
>>> str1 = '我是周蘿卜,今年18歲'
>>> re.sub(r"\d+", "20", str1)
'我是周蘿卜,今年20歲'
96. 讀取大文件(🧡🧡)
97. 輸入日期, 判斷這一天是這一年的第幾天
98. 排序
99. 將字符串處理成字典
100. 下面代碼的輸出結果將是什么?
補充 被問的
101 python協程 異步
協程 線程 進程都屬于并發;并發是在一個處理器上輪流處理任務,強調資源的共享和分配;并行是在多個處理器上同時處理任務,強調硬件資源的利用。
asyncio:異步函數庫
request : 同步函數庫
詳細見metagpt異步編程
102 python子類不用super調用父類屬性
不用super一般是不可以調用父類的方法的,但是子類執行行,父類執行__new__ 函數(創建實例),所以想不用super調用父類可以寫到__new__里
問題參考自python八股