一、python 的數(shù)據(jù)結(jié)構(gòu)
1.1 基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)
首先我們介紹一下python的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu):Python中的數(shù)據(jù)結(jié)構(gòu)是組織和存儲(chǔ)數(shù)據(jù)的方式,它們使得數(shù)據(jù)的處理更為高效和靈活。Python內(nèi)置了多種數(shù)據(jù)結(jié)構(gòu),主要包括列表(list)、元組(tuple)、集合(set)和字典(dict)。
- 列表(List):列表是Python中最常用的數(shù)據(jù)結(jié)構(gòu)之一,它是一個(gè)有序的元素集合。列表中的元素可以是任意類型,包括數(shù)字、字符串、其他列表等。列表是可變的,這意味著你可以添加、刪除或修改列表中的元素。
- 元組(Tuple):元組與列表類似,也是一個(gè)有序的元素集合。然而,元組是不可變的,一旦創(chuàng)建,就不能修改其元素。這使得元組在某些情況下更為安全,例如,當(dāng)你不希望數(shù)據(jù)被意外修改時(shí)。
- 集合(Set):集合是一個(gè)無(wú)序的、不重復(fù)元素的集合。集合主要用于成員關(guān)系測(cè)試和消除重復(fù)元素。集合支持集合運(yùn)算,如并集、交集和差集等。
- 字典(Dict):字典是一個(gè)無(wú)序的鍵值對(duì)集合。字典中的每個(gè)元素都是一個(gè)鍵值對(duì),鍵是唯一的,用于查找對(duì)應(yīng)的值。字典在存儲(chǔ)需要快速查找的數(shù)據(jù)時(shí)非常有用。
1.2 collections
在Python中,collections
模塊提供了一些特殊的高階容器數(shù)據(jù)類型,這些類型擴(kuò)展了Python內(nèi)置的容器類型,提供了更多有用的功能和操作。下面是collections
模塊中一些常用容器數(shù)據(jù)類型的介紹:
-
namedtuple
:namedtuple
是一個(gè)工廠函數(shù),用于創(chuàng)建具有名稱的元組子類。這使得元組的每個(gè)元素都擁有一個(gè)描述性的名稱,從而提高了代碼的可讀性。通過(guò)名稱來(lái)訪問(wèn)元組的元素,而不是使用索引,可以使代碼更加直觀。 -
deque
:deque
是一個(gè)雙端隊(duì)列,支持從隊(duì)列的兩端添加和移除元素。相比于Python的列表(list),deque
在處理隊(duì)列操作(如插入和刪除)時(shí)更加高效,尤其是在隊(duì)列的兩端。 -
Counter
:Counter
是一個(gè)字典子類,用于計(jì)數(shù)可哈希對(duì)象。它提供了計(jì)數(shù)和統(tǒng)計(jì)功能,常用于統(tǒng)計(jì)元素出現(xiàn)的次數(shù)。Counter
對(duì)象支持多種數(shù)學(xué)運(yùn)算,如加法、減法、交集和并集等。 -
OrderedDict
:OrderedDict
是一個(gè)保持元素插入順序的字典子類。普通的Python字典是無(wú)序的,而OrderedDict
則記住了元素被插入時(shí)的順序。這使得OrderedDict
在處理需要保持順序的場(chǎng)景時(shí)非常有用。 -
defaultdict
:defaultdict
是一個(gè)字典子類,它提供了一個(gè)默認(rèn)值工廠函數(shù)。當(dāng)查詢一個(gè)不存在的鍵時(shí),defaultdict
會(huì)自動(dòng)使用工廠函數(shù)創(chuàng)建一個(gè)默認(rèn)值,而不是引發(fā)KeyError
異常。這可以簡(jiǎn)化代碼,避免不必要的錯(cuò)誤處理。 -
ChainMap
:ChainMap
可以將多個(gè)字典鏈接在一起,形成一個(gè)邏輯上的單個(gè)字典。在查找時(shí),ChainMap
會(huì)按照字典的鏈接順序進(jìn)行查找,直到找到對(duì)應(yīng)的鍵為止。這提供了一種方便的方式來(lái)組合多個(gè)字典,并簡(jiǎn)化查找操作。
1.3 heapq
heapq是Python標(biāo)準(zhǔn)庫(kù)中的一個(gè)模塊,它提供了堆隊(duì)列算法的實(shí)現(xiàn),也稱為優(yōu)先隊(duì)列算法。堆是一種特殊的樹(shù)形數(shù)據(jù)結(jié)構(gòu),通常表現(xiàn)為一個(gè)完全二叉樹(shù),它滿足堆屬性:父節(jié)點(diǎn)的值總是大于或等于(最大堆)或小于或等于(最小堆)其子節(jié)點(diǎn)的值。在Python的heapq模塊中,默認(rèn)實(shí)現(xiàn)的是最小堆。
heapq模塊的主要用途是實(shí)現(xiàn)對(duì)一組數(shù)據(jù)進(jìn)行排序和取最?。ɑ蜃畲螅┲?,它支持添加、彈出、替換等操作,同時(shí)提供了建堆、堆排序等高級(jí)功能。這些操作的時(shí)間復(fù)雜度通常較低,因此heapq在處理大量數(shù)據(jù)時(shí)非常高效。
二、python 的基礎(chǔ)語(yǔ)法
Python 是一種解釋型、交互式、面向?qū)ο蟮木幊陶Z(yǔ)言。它的語(yǔ)法簡(jiǎn)潔清晰,易于學(xué)習(xí),并且具有強(qiáng)大的功能。
2.1 Python的變量與賦值
在Python中,變量是一個(gè)標(biāo)識(shí)符(名稱),它用于存儲(chǔ)程序中使用的值。賦值操作是將一個(gè)值賦給變量的過(guò)程。Python中的變量不需要事先聲明,可以直接使用賦值語(yǔ)句來(lái)創(chuàng)建和初始化。
2.1.1 變量的命名規(guī)則
- 變量名只能包含字母、數(shù)字和下劃線。
- 變量名不能以數(shù)字開(kāi)頭。
- 變量名是區(qū)分大小寫的,例如
myVar
和myvar
被視為兩個(gè)不同的變量。 - 避免使用Python的保留字(如
if
、for
、while
等)作為變量名。
2.1.2 賦值操作
在Python中,賦值操作使用單個(gè)等號(hào)=
。等號(hào)左邊是變量名,右邊是要賦給變量的值。
# 賦值給變量
x = 10 # 整數(shù)賦值
y = 3.14 # 浮點(diǎn)數(shù)賦值
name = "Alice" # 字符串賦值
is_student = True # 布爾值賦值
# 賦值后,變量的值可以改變
x = 20 # 現(xiàn)在x的值是20
# 也可以將其他變量的值賦給變量
z = x # 現(xiàn)在z的值也是20,且如果x改變,z不會(huì)隨之改變(除非再次賦值)
2.1.2 變量的類型
Python是動(dòng)態(tài)類型語(yǔ)言,意味著變量的類型在運(yùn)行時(shí)確定,并且可以改變。
# 初始化為整數(shù)
a = 10
print(type(a)) # 輸出: <class 'int'>
# 改變?yōu)樽址?/span>
a = "hello"
print(type(a)) # 輸出: <class 'str'>
2.1.3 變量的作用域
變量的作用域決定了變量在程序中的可見(jiàn)性和生命周期。Python中的變量作用域可以是:
- 局部作用域:在函數(shù)或方法內(nèi)部定義的變量。
- 全局作用域:在函數(shù)或方法外部定義的變量。
-
內(nèi)建作用域:內(nèi)建函數(shù)和異常的名字(例如
abs()
、len()
等)。
當(dāng)在函數(shù)內(nèi)部引用一個(gè)變量時(shí),Python首先檢查局部作用域,然后是全局作用域,最后是內(nèi)建作用域。
# 全局作用域中的變量
global_var = 100
def my_function():
# 局部作用域中的變量
local_var = 200
print(local_var) # 輸出200
print(global_var) # 輸出100,因?yàn)榭梢栽L問(wèn)全局作用域中的變量
my_function()
print(local_var) # 報(bào)錯(cuò),因?yàn)閘ocal_var只在my_function的局部作用域中定義
2.1.4 鏈?zhǔn)劫x值和多重賦值
Python還支持鏈?zhǔn)劫x值和多重賦值。
# 鏈?zhǔn)劫x值
a = b = c = 10 # a, b, 和 c 現(xiàn)在都指向同一個(gè)整數(shù)對(duì)象10
# 多重賦值
x, y, z = 1, 2, 3 # x現(xiàn)在是1, y現(xiàn)在是2, z現(xiàn)在是3
2.2 運(yùn)算符
運(yùn)算符 | 運(yùn)算符類型 | 運(yùn)算符描述 | 優(yōu)先級(jí) | 示例 | ||
---|---|---|---|---|---|---|
+ |
算術(shù) | 加法 | 5 | a + b |
||
- |
算術(shù) | 減法 | 5 | a - b |
||
* |
算術(shù) | 乘法 | 4 | a * b |
||
/ |
算術(shù) | 除法 | 4 | a / b |
||
// |
算術(shù) | 整除(向下取整) | 4 | a // b |
||
% |
算術(shù) | 取模(求余數(shù)) | 4 | a % b |
||
** |
算術(shù) | 冪運(yùn)算 | 3 | a ** b |
||
+= |
賦值 | 加法賦值 | - | a += b |
||
-= |
賦值 | 減法賦值 | - | a -= b |
||
*= |
賦值 | 乘法賦值 | - | a *= b |
||
/= |
賦值 | 除法賦值 | - | a /= b |
||
//= |
賦值 | 整除賦值 | - | a //= b |
||
%= |
賦值 | 取模賦值 | - | a %= b |
||
**= |
賦值 | 冪賦值 | - | a **= b |
||
== |
比較 | 等于 | 6 | a == b |
||
!= |
比較 | 不等于 | 6 | a != b |
||
> |
比較 | 大于 | 6 | a > b |
||
< |
比較 | 小于 | 6 | a < b |
||
>= |
比較 | 大于等于 | 6 | a >= b |
||
<= |
比較 | 小于等于 | 6 | a <= b |
||
and |
邏輯 | 邏輯與 | - | a and b |
||
or |
邏輯 | 邏輯或 | - | a or b |
||
not |
邏輯 | 邏輯非 | - | not a |
||
& |
位運(yùn)算 | 按位與 | - | a & b |
||
| |
位運(yùn)算 | 按位或 | - | a | b |
||
^ |
位運(yùn)算 | 按位異或 | - | a ^ b |
||
~ |
位運(yùn)算 | 按位取反 | - | ~a |
||
<< |
位運(yùn)算 | 左移 | - | a << b |
||
>> |
位運(yùn)算 | 右移 | - | a >> b |
||
is |
身份 | 判斷兩個(gè)對(duì)象是否相同(即是否引用自同一個(gè)對(duì)象) | - | a is b |
||
is not |
身份 | 判斷兩個(gè)對(duì)象是否不同 | - | a is not b |
||
in |
成員 | 檢查一個(gè)值是否存在于一個(gè)序列中 | - | a in b |
||
not in |
成員 | 檢查一個(gè)值是否不存在于一個(gè)序列中 | - | a not in b |
為了確保優(yōu)先級(jí),請(qǐng)寫代碼的同時(shí)加入上括號(hào)。
2.3 控制流算法
在 Python 中,控制流指的是程序執(zhí)行過(guò)程中根據(jù)某些條件或邏輯來(lái)改變執(zhí)行路徑的機(jī)制。這包括條件語(yǔ)句、循環(huán)語(yǔ)句以及異常處理。以下是 Python 中控制流的一些關(guān)鍵組件的詳細(xì)介紹:
2.3.1 條件語(yǔ)句
if 語(yǔ)句:用于根據(jù)條件執(zhí)行不同的代碼塊。
if condition:
# 執(zhí)行當(dāng) condition 為 True 時(shí)的代碼塊
elif another_condition:
# 執(zhí)行當(dāng) condition 為 False 且 another_condition 為 True 時(shí)的代碼塊
else:
# 執(zhí)行當(dāng)所有條件都不滿足時(shí)的代碼塊
三元運(yùn)算符:是 if-else 語(yǔ)句的簡(jiǎn)潔形式,用于在單行中根據(jù)條件返回兩個(gè)值中的一個(gè)。
value_if_true if condition else value_if_false
2.3.2 循環(huán)語(yǔ)句
for 循環(huán):用于遍歷序列(如列表、元組、字符串等)或任何可迭代對(duì)象的元素。
for item in iterable:
# 對(duì)每個(gè) item 執(zhí)行代碼塊
while 循環(huán):只要給定的條件為真,就重復(fù)執(zhí)行代碼塊。
while condition:
# 當(dāng) condition 為 True 時(shí),執(zhí)行代碼塊
2.3.3 異常處理
try-except 語(yǔ)句:用于捕獲和處理運(yùn)行時(shí)錯(cuò)誤或異常。
try:
# 嘗試執(zhí)行的代碼塊
except ExceptionType:
# 當(dāng)發(fā)生 ExceptionType 異常時(shí)執(zhí)行的代碼塊
else:
# 當(dāng) try 塊成功執(zhí)行完畢后執(zhí)行的代碼塊
finally:
# 無(wú)論是否發(fā)生異常,都會(huì)執(zhí)行的代碼塊
raise 語(yǔ)句:用于顯式地引發(fā)一個(gè)異常。
raise ExceptionType("Error message")
2.3.4 中斷和繼續(xù)循環(huán)
break 語(yǔ)句:用于跳出當(dāng)前循環(huán)(無(wú)論是 for 循環(huán)還是 while 循環(huán))。
for item in iterable:
if condition:
break # 當(dāng)滿足條件時(shí)跳出循環(huán)
continue 語(yǔ)句:用于跳過(guò)當(dāng)前循環(huán)的剩余部分,并立即開(kāi)始下一次迭代。
for item in iterable:
if condition:
continue # 當(dāng)滿足條件時(shí)跳過(guò)當(dāng)前迭代
# 執(zhí)行其余的代碼
2.3.5 上下文管理器
with 語(yǔ)句:用于簡(jiǎn)化資源管理,如文件操作、網(wǎng)絡(luò)連接或鎖定機(jī)制。上下文管理器確保資源在使用后被正確清理。
with context_expression as variable:
# 在此塊內(nèi),variable 綁定到 context_expression 的結(jié)果
# 當(dāng)退出此塊時(shí),context_expression 定義的清理操作被執(zhí)行
以上是 Python 中控制流的一些主要組件。它們?cè)试S你根據(jù)條件、循環(huán)或異常來(lái)組織你的代碼,以創(chuàng)建靈活和健壯的程序。
2.4 類與對(duì)象
當(dāng)然可以。在Python中,類和對(duì)象是面向?qū)ο缶幊蹋∣OP)的兩個(gè)核心概念。面向?qū)ο缶幊淌且环N編程范式,它使用“對(duì)象”來(lái)設(shè)計(jì)應(yīng)用程序和軟件。對(duì)象通常具有屬性和方法,它們分別表示對(duì)象的數(shù)據(jù)和行為。
2.4.1 類(Class)
類是一個(gè)抽象的概念,它定義了對(duì)象的屬性和方法。你可以將類視為對(duì)象的藍(lán)圖或模板,它描述了如何創(chuàng)建特定類型的對(duì)象。類定義了對(duì)象的狀態(tài)(屬性)和行為(方法)。
在Python中,你可以使用class
關(guān)鍵字來(lái)定義一個(gè)類。下面是一個(gè)簡(jiǎn)單的類定義示例:
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def bark(self):
print(f"{self.name} is barking!")
def describe(self):
print(f"{self.name} is {self.age} years old.")
在這個(gè)例子中,Dog
是一個(gè)類,它有兩個(gè)屬性(name
和age
)和兩個(gè)方法(bark
和describe
)。__init__
方法是一個(gè)特殊方法,用于初始化新創(chuàng)建的對(duì)象的狀態(tài)。當(dāng)你創(chuàng)建一個(gè)Dog
對(duì)象時(shí),Python會(huì)自動(dòng)調(diào)用這個(gè)方法。
2.4.2 對(duì)象(Object)
對(duì)象是類的實(shí)例。你可以通過(guò)調(diào)用類來(lái)創(chuàng)建一個(gè)或多個(gè)對(duì)象。每個(gè)對(duì)象都有它自己的屬性和方法,并且這些屬性和方法是從類中繼承的。
下面是如何創(chuàng)建一個(gè)Dog
類的實(shí)例(即對(duì)象)的示例:
# 創(chuàng)建Dog類的實(shí)例(對(duì)象)
my_dog = Dog("Buddy", 3)
# 訪問(wèn)對(duì)象的屬性
print(my_dog.name) # 輸出: Buddy
print(my_dog.age) # 輸出: 3
# 調(diào)用對(duì)象的方法
my_dog.bark() # 輸出: Buddy is barking!
my_dog.describe() # 輸出: Buddy is 3 years old.
在這個(gè)例子中,my_dog
是一個(gè)Dog
類的實(shí)例(對(duì)象)。我們給my_dog
對(duì)象賦予了特定的屬性值(name
為"Buddy",age
為3),并調(diào)用了它的方法。
2.4.3 繼承
在面向?qū)ο缶幊讨?,一個(gè)類可以繼承另一個(gè)類的屬性和方法。這允許你創(chuàng)建更通用的類,并從這些通用類中派生更具體的類。在Python中,你可以使用class
關(guān)鍵字和繼承的語(yǔ)法來(lái)定義子類。
class Labrador(Dog):
def swim(self):
print(f"{self.name} is swimming!")
# 創(chuàng)建Labrador類的實(shí)例
my_labrador = Labrador("Labrador Retriever", 2)
# 調(diào)用繼承自Dog的方法
my_labrador.bark() # 輸出: Labrador Retriever is barking!
my_labrador.describe() # 輸出: Labrador Retriever is 2 years old.
# 調(diào)用Labrador特有的方法
my_labrador.swim() # 輸出: Labrador Retriever is swimming!
在這個(gè)例子中,Labrador
類繼承自Dog
類,因此它自動(dòng)獲得了Dog
類的所有屬性和方法。此外,Labrador
類還定義了一個(gè)特有的方法swim
。
通過(guò)類和對(duì)象,你可以構(gòu)建復(fù)雜且可維護(hù)的程序結(jié)構(gòu),實(shí)現(xiàn)代碼重用和模塊化,以及更好地組織和理解你的程序邏輯。
2.5 導(dǎo)入模塊
在Python中,導(dǎo)入模塊是一個(gè)重要的功能,它允許你使用其他Python文件(即模塊)中定義的函數(shù)、類和變量。這樣,你可以將代碼組織成多個(gè)可重用的組件,并在需要時(shí)將它們導(dǎo)入到你的主程序中。
2.5.1 導(dǎo)入整個(gè)模塊
你可以使用import
語(yǔ)句來(lái)導(dǎo)入整個(gè)模塊。一旦模塊被導(dǎo)入,你就可以使用點(diǎn)操作符(.
)來(lái)訪問(wèn)模塊中的函數(shù)、類或變量。
import math
# 使用模塊中的函數(shù)
radius = 5
area = math.pi * radius ** 2
print(area)
在這個(gè)例子中,我們導(dǎo)入了math
模塊,并使用它來(lái)計(jì)算圓的面積。注意我們使用了math.pi
來(lái)訪問(wèn)math
模塊中定義的pi
常量。
2.5.2 導(dǎo)入模塊中的特定部分
如果你只對(duì)模塊中的某些函數(shù)或變量感興趣,你可以使用from ... import ...
語(yǔ)法來(lái)只導(dǎo)入它們。
from math import sqrt, pi
# 直接使用函數(shù)和變量,無(wú)需前綴
side_length = 9
diagonal = sqrt(2) * side_length
area_of_circle = pi * (side_length / 2) ** 2
print(diagonal)
print(area_of_circle)
在這個(gè)例子中,我們只導(dǎo)入了math
模塊中的sqrt
和pi
函數(shù)/變量,因此我們可以直接使用它們的名字,而不需要加上math.
前綴。
2.5.3 導(dǎo)入模塊并為其指定別名
如果模塊的名字太長(zhǎng)或者可能與你的程序中的其他部分沖突,你可以使用as
關(guān)鍵字為它指定一個(gè)別名。
import numpy as np
# 使用別名來(lái)調(diào)用模塊中的函數(shù)
array = np.array([1, 2, 3, 4])
print(array)
在這個(gè)例子中,我們導(dǎo)入了numpy
模塊并為其指定了別名np
。這樣,我們就可以使用np
來(lái)代替numpy
來(lái)調(diào)用它的函數(shù)和類。
2.5.4 從包中導(dǎo)入模塊
Python的模塊可以組織成包(packages),包是包含多個(gè)模塊的目錄,這些模塊通常具有某種共同的功能或目的。你可以使用點(diǎn)操作符來(lái)從包中導(dǎo)入模塊。
假設(shè)你有一個(gè)名為mypackage
的包,它包含一個(gè)名為mymodule
的模塊,你可以這樣導(dǎo)入它:
from mypackage import mymodule
# 使用模塊中的函數(shù)或類
result = mymodule.some_function()
print(result)
或者,如果你知道你要從哪個(gè)模塊中導(dǎo)入什么,你可以直接這樣做:
from mypackage.mymodule import some_function
# 直接使用函數(shù)
result = some_function()
print(result)
2.5.5 動(dòng)態(tài)導(dǎo)入模塊
有時(shí),你可能希望在運(yùn)行時(shí)根據(jù)某些條件動(dòng)態(tài)地導(dǎo)入模塊。這可以通過(guò)使用importlib
模塊的import_module
函數(shù)來(lái)實(shí)現(xiàn)。
import importlib
module_name = 'math' # 可以是任何有效的模塊名
module = importlib.import_module(module_name)
# 使用導(dǎo)入的模塊
print(module.sqrt(16)) # 輸出: 4.0
在這個(gè)例子中,我們根據(jù)module_name
變量的值動(dòng)態(tài)地導(dǎo)入了模塊,并使用它來(lái)計(jì)算平方根。
導(dǎo)入模塊是Python編程中的一個(gè)基本且強(qiáng)大的功能,它允許你構(gòu)建大型、可維護(hù)的程序,同時(shí)保持代碼的清晰和模塊化。
2.6 迭代器
在Python中,迭代器(Iterator)是一個(gè)可以記住遍歷的位置的對(duì)象,它可以從頭到尾訪問(wèn)數(shù)據(jù)集合的元素。迭代器是數(shù)據(jù)集合的訪問(wèn)接口,它只能從前往后訪問(wèn)數(shù)據(jù)集合中的元素,并且只能訪問(wèn)一次。迭代器提供了一種不依賴于索引的迭代訪問(wèn)方法,使得遍歷數(shù)據(jù)集合變得更為簡(jiǎn)單和高效。
迭代器對(duì)象實(shí)現(xiàn)了迭代器協(xié)議,即它必須擁有__iter__()
方法和__next__()
方法。__iter__()
方法返回迭代器對(duì)象本身,而__next__()
方法返回?cái)?shù)據(jù)集合的下一個(gè)元素。當(dāng)沒(méi)有更多元素可供訪問(wèn)時(shí),__next__()
方法將引發(fā)StopIteration
異常。
Python中的許多內(nèi)置數(shù)據(jù)結(jié)構(gòu)(如列表、元組、字典和集合)都是可迭代的,這意味著它們可以自動(dòng)與for循環(huán)或其他迭代器操作一起使用。然而,不是所有的數(shù)據(jù)結(jié)構(gòu)都是迭代器。為了將一個(gè)可迭代對(duì)象轉(zhuǎn)換為迭代器,我們可以使用內(nèi)置的iter()
函數(shù)。
下面是一個(gè)簡(jiǎn)單的迭代器示例:
class MyIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index < len(self.data):
result = self.data[self.index]
self.index += 1
return result
else:
raise StopIteration
# 使用迭代器
my_iterator = MyIterator([1, 2, 3, 4, 5])
for item in my_iterator:
print(item)
在這個(gè)示例中,我們定義了一個(gè)名為MyIterator
的類,它實(shí)現(xiàn)了迭代器協(xié)議。我們可以創(chuàng)建這個(gè)類的實(shí)例,并將其用于for循環(huán)中,以迭代訪問(wèn)數(shù)據(jù)集合中的元素。
總的來(lái)說(shuō),迭代器提供了一種強(qiáng)大而靈活的方式來(lái)遍歷數(shù)據(jù)集合。通過(guò)使用迭代器,我們可以避免在遍歷過(guò)程中使用索引,并且可以更容易地處理動(dòng)態(tài)變化的數(shù)據(jù)集合。
2.7 裝飾器
在Python中,裝飾器(Decorator)是一個(gè)高級(jí)功能,它允許你修改或增強(qiáng)函數(shù)、方法或類的行為,而無(wú)需改變其源代碼。裝飾器本質(zhì)上是一個(gè)接受函數(shù)作為參數(shù)的可調(diào)用對(duì)象(通常是一個(gè)函數(shù)),并返回一個(gè)修改后的函數(shù)。
裝飾器的語(yǔ)法使用@
符號(hào),它放在要修飾的函數(shù)或類的定義之前。這使得裝飾器的應(yīng)用非常直觀和簡(jiǎn)潔。
下面是一個(gè)簡(jiǎn)單的裝飾器示例,它用于記錄函數(shù)的執(zhí)行時(shí)間:
import time
def timing_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function {func.__name__} took {end_time - start_time:.6f} seconds to execute.")
return result
return wrapper
@timing_decorator
def my_function():
time.sleep(1) # 模擬耗時(shí)操作
print("Function executed!")
# 調(diào)用函數(shù)時(shí),裝飾器會(huì)自動(dòng)生效
my_function()
在這個(gè)例子中,timing_decorator
是一個(gè)裝飾器函數(shù),它接受一個(gè)函數(shù)func
作為參數(shù),并返回一個(gè)新的函數(shù)wrapper
。wrapper
函數(shù)在調(diào)用原函數(shù)之前和之后分別記錄了時(shí)間,并打印出執(zhí)行耗時(shí)。當(dāng)我們?cè)?code>my_function的定義前使用@timing_decorator
語(yǔ)法時(shí),Python解釋器會(huì)自動(dòng)將my_function
替換為timing_decorator(my_function)
的返回值,即wrapper
函數(shù)。因此,當(dāng)我們調(diào)用my_function()
時(shí),實(shí)際上是調(diào)用了wrapper()
,從而實(shí)現(xiàn)了執(zhí)行時(shí)間的記錄。
裝飾器可以用于多種場(chǎng)景,比如日志記錄、性能分析、權(quán)限校驗(yàn)、緩存等。它們提供了一種靈活且可重用的方式來(lái)擴(kuò)展函數(shù)或類的功能,而無(wú)需修改其源代碼。這使得代碼更加模塊化和可維護(hù)。
需要注意的是,裝飾器在函數(shù)定義時(shí)立即執(zhí)行,并且會(huì)改變?cè)泻瘮?shù)的引用。因此,在使用裝飾器時(shí)需要謹(jǐn)慎,確保理解其工作原理和潛在影響。
三、Python的機(jī)制
Python的各類機(jī)制主要包括其執(zhí)行機(jī)制、內(nèi)存管理機(jī)制、錯(cuò)誤處理機(jī)制以及模塊導(dǎo)入機(jī)制等。下面我將逐一為您介紹這些機(jī)制。
3.1 執(zhí)行機(jī)制
Python 是一種解釋型語(yǔ)言,它的執(zhí)行機(jī)制涉及幾個(gè)關(guān)鍵步驟:
- 編譯:當(dāng)Python腳本運(yùn)行時(shí),它首先將源代碼(.py文件)逐行編譯成字節(jié)碼。這些字節(jié)碼是源代碼的底層、平臺(tái)無(wú)關(guān)的表現(xiàn)形式,用于提高執(zhí)行速度。如果Python具有寫入權(quán)限,它會(huì)將這組字節(jié)碼保存為.pyc文件,以便下次運(yùn)行時(shí)直接加載,從而提高啟動(dòng)速度。
- 執(zhí)行:編譯后的字節(jié)碼被發(fā)送到Python虛擬機(jī)(PVM)上執(zhí)行。PVM是Python的運(yùn)行引擎,負(fù)責(zé)迭代運(yùn)行字節(jié)碼指令,完成操作。
3.2 內(nèi)存管理機(jī)制
Python具有自動(dòng)內(nèi)存管理機(jī)制,主要包括引用計(jì)數(shù)、垃圾回收和分代收集。
- 引用計(jì)數(shù):Python通過(guò)引用計(jì)數(shù)來(lái)跟蹤對(duì)象的引用次數(shù)。當(dāng)對(duì)象的引用計(jì)數(shù)減少到0時(shí),Python的垃圾回收器會(huì)將其內(nèi)存釋放。
- 垃圾回收:當(dāng)引用計(jì)數(shù)無(wú)法處理循環(huán)引用時(shí),Python的垃圾回收器會(huì)介入,通過(guò)標(biāo)記-清除算法來(lái)識(shí)別并釋放不再使用的對(duì)象。
- 分代收集:Python還采用了分代收集策略,根據(jù)對(duì)象的存活時(shí)間來(lái)優(yōu)化垃圾回收過(guò)程。
3.3 錯(cuò)誤處理機(jī)制
Python使用異常處理機(jī)制來(lái)處理運(yùn)行時(shí)錯(cuò)誤。通過(guò)try
、except
、finally
和raise
等關(guān)鍵字,開(kāi)發(fā)者可以捕獲和處理異常,確保程序的健壯性。
3.4 全局解釋器鎖
全局解釋器鎖(Global Interpreter Lock,GIL)是計(jì)算機(jī)程序設(shè)計(jì)語(yǔ)言解釋器用于同步線程的一種機(jī)制,它使得任何時(shí)刻僅有一個(gè)線程在執(zhí)行。在Python語(yǔ)言的主流實(shí)現(xiàn)CPython中,GIL是一個(gè)貨真價(jià)實(shí)的全局線程鎖,用于確保在任何給定時(shí)間只有一個(gè)線程執(zhí)行Python字節(jié)碼。
具體來(lái)說(shuō),在解釋器解釋執(zhí)行任何Python代碼時(shí),都需要先獲得這把鎖。在遇到I/O操作時(shí),GIL會(huì)釋放,以便其他線程有機(jī)會(huì)執(zhí)行。對(duì)于純計(jì)算的程序,沒(méi)有I/O操作,解釋器會(huì)每隔100次操作就釋放這把鎖,讓別的線程有機(jī)會(huì)執(zhí)行(這個(gè)次數(shù)可以通過(guò)sys.setcheckinterval來(lái)調(diào)整)。因此,雖然CPython的線程庫(kù)直接封裝了操作系統(tǒng)的原生線程,但CPython進(jìn)程作為一個(gè)整體,同一時(shí)間只會(huì)有一個(gè)獲得了GIL的線程在運(yùn)行,其他的線程都處于等待狀態(tài),等待GIL的釋放。
GIL的存在主要是由于CPython解釋器的設(shè)計(jì)和實(shí)現(xiàn)方式。它作為一種互斥鎖,用于保護(hù)Python對(duì)象和內(nèi)存管理機(jī)制,防止多個(gè)線程同時(shí)訪問(wèn)和修改Python解釋器的內(nèi)部狀態(tài)。
然而,GIL也帶來(lái)了一些局限性。它限制了多線程Python程序充分利用多個(gè)CPU核心的能力,特別是對(duì)于CPU密集型任務(wù)。這可能會(huì)影響需要大量計(jì)算的應(yīng)用程序的性能。不過(guò),對(duì)于I/O密集型任務(wù),雖然多線程的優(yōu)勢(shì)不明顯,但Python線程在等待I/O操作完成時(shí)仍然可以釋放GIL,因此仍具有一定的優(yōu)勢(shì)。
3.5 模塊導(dǎo)入機(jī)制
Python的模塊導(dǎo)入機(jī)制允許開(kāi)發(fā)者將代碼組織成多個(gè)可重用的組件(即模塊)。通過(guò)import
語(yǔ)句,開(kāi)發(fā)者可以導(dǎo)入并使用其他模塊中的函數(shù)、類和變量。此外,Python還支持動(dòng)態(tài)導(dǎo)入模塊和從包中導(dǎo)入模塊,為大型項(xiàng)目的組織提供了靈活性。
3.6 其他機(jī)制
除了上述機(jī)制外,Python還具有其他重要的機(jī)制,如上下文管理(通過(guò)with
語(yǔ)句實(shí)現(xiàn))、迭代器與生成器(用于高效遍歷數(shù)據(jù)集合)、裝飾器(用于修改或增強(qiáng)函數(shù)、方法或類的行為)等。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-845172.html
這些機(jī)制共同構(gòu)成了Python強(qiáng)大的功能和易用性,使其在各種應(yīng)用場(chǎng)景中都能發(fā)揮出色。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-845172.html
到了這里,關(guān)于第一章 Python的基礎(chǔ)語(yǔ)法的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!