最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python裝飾器基礎(chǔ)詳解

 更新時(shí)間:2016年03月09日 14:03:48   作者:GEJUNQIANG  
裝飾器(decorator)是一種高級(jí)Python語(yǔ)法。裝飾器可以對(duì)一個(gè)函數(shù)、方法或者類(lèi)進(jìn)行加工。接下來(lái)通過(guò)本文給大家介紹python裝飾器基礎(chǔ),對(duì)python裝飾器相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧

裝飾器(decorator)是一種高級(jí)Python語(yǔ)法。裝飾器可以對(duì)一個(gè)函數(shù)、方法或者類(lèi)進(jìn)行加工。在Python中,我們有多種方法對(duì)函數(shù)和類(lèi)進(jìn)行加工,比如在Python閉包中,我們見(jiàn)到函數(shù)對(duì)象作為某一個(gè)函數(shù)的返回結(jié)果。相對(duì)于其它方式,裝飾器語(yǔ)法簡(jiǎn)單,代碼可讀性高。因此,裝飾器在Python項(xiàng)目中有廣泛的應(yīng)用。

前面快速介紹了裝飾器的語(yǔ)法,在這里,我們將深入裝飾器內(nèi)部工作機(jī)制,更詳細(xì)更系統(tǒng)地介紹裝飾器的內(nèi)容,并學(xué)習(xí)自己編寫(xiě)新的裝飾器的更多高級(jí)語(yǔ)法。

什么是裝飾器

裝飾是為函數(shù)和類(lèi)指定管理代碼的一種方式。Python裝飾器以?xún)煞N形式呈現(xiàn):

【1】函數(shù)裝飾器在函數(shù)定義的時(shí)候進(jìn)行名稱(chēng)重綁定,提供一個(gè)邏輯層來(lái)管理函數(shù)和方法或隨后對(duì)它們的調(diào)用。

【2】類(lèi)裝飾器在類(lèi)定義的時(shí)候進(jìn)行名稱(chēng)重綁定,提供一個(gè)邏輯層來(lái)管理類(lèi),或管理隨后調(diào)用它們所創(chuàng)建的實(shí)例。

簡(jiǎn)而言之,裝飾器提供了一種方法,在函數(shù)和類(lèi)定義語(yǔ)句的末尾插入自動(dòng)運(yùn)行的代碼——對(duì)于函數(shù)裝飾器,在def的末尾;對(duì)于類(lèi)裝飾器,在class的末尾。這樣的代碼可以扮演不同的角色。
裝飾器提供了一些和代碼維護(hù)性和審美相關(guān)的有點(diǎn)。此外,作為結(jié)構(gòu)化工具,裝飾器自然地促進(jìn)了代碼封裝,這減少了冗余性并使得未來(lái)變得更容易。

函數(shù)裝飾器

通過(guò)在一個(gè)函數(shù)的def語(yǔ)句的末尾運(yùn)行另一個(gè)函數(shù),把最初的函數(shù)名重新綁定到結(jié)果。

用法

裝飾器在緊挨著定義一個(gè)函數(shù)或方法的def語(yǔ)句之前的一行編寫(xiě),并且它由@符號(hào)以及緊隨其后的對(duì)于元函數(shù)的一個(gè)引用組成——這是管理另一個(gè)函數(shù)的一個(gè)函數(shù)(或其他可調(diào)用對(duì)象)。
在編碼上,函數(shù)裝飾器自動(dòng)將如下語(yǔ)法:

@decorator 
def F(arg): 
... 
F(99)

映射為這個(gè)對(duì)等形式:

def F(arg): 
... 
F = decorator(F) 
F(99)

這里的裝飾器是一個(gè)單參數(shù)的可調(diào)用對(duì)象,它返回與F具有相同數(shù)目的參數(shù)的一個(gè)可調(diào)用對(duì)象。
當(dāng)隨后調(diào)用F函數(shù)的時(shí)候,它自動(dòng)調(diào)用裝飾器所返回的對(duì)象。

換句話(huà)說(shuō),裝飾實(shí)際把如下的第一行映射為第二行(盡管裝飾器只在裝飾的時(shí)候運(yùn)行一次)

fun(6,7) 
decorator(func)(6,7) 

這一自動(dòng)名稱(chēng)重綁定也解釋了之前介紹的靜態(tài)方法和property裝飾器語(yǔ)法的原因:

class C: 
@staticmethod 
def meth(...):... 
@property 
def name(self):...

實(shí)現(xiàn)

裝飾器自身是返回可調(diào)用對(duì)象的可調(diào)用對(duì)象。實(shí)際上,它可以是任意類(lèi)型的可調(diào)用對(duì)象,并且返回任意類(lèi)型的可調(diào)用對(duì)象:函數(shù)和類(lèi)的任何組合都可以使用,盡管一些組合更適合于特定的背景。

有一種常用的編碼模式——裝飾器返回了一個(gè)包裝器,包裝器把最初的函數(shù)保持到一個(gè)封閉的作用域中:

def decorator(F): 
def wrapper(*args): 
# 使用 F 和 *args 
# 調(diào)用原來(lái)的F(*args) 
return wrapper 
@decorator 
def func(x,y): 
... 
func(6,7)

當(dāng)隨后調(diào)用名稱(chēng)func的時(shí)候,它確實(shí)調(diào)用裝飾器所返回的包裝器函數(shù);隨后包裝器函數(shù)可能運(yùn)行最初的func,因?yàn)樗谝粋€(gè)封閉的作用域中仍然可以使用。

為了對(duì)類(lèi)做同樣的事情,我們可以重載調(diào)用操作:

class decorator: 
def __init__(self,func): 
self.func = func 
def __call__(self,*args): 
# 使用self.func和args 
# self.func(*args)調(diào)用最初的func 
@decorator 
def func(x,y): 
... 
func(6,7)

但是,要注意的是,基于類(lèi)的代碼中,它對(duì)于攔截簡(jiǎn)單函數(shù)有效,但當(dāng)它應(yīng)用于類(lèi)方法函數(shù)時(shí),并不很有效:
如下反例:

class decorator: 
def __init__(self,func): 
self.func = func 
def __call__(self,*args): 
# 調(diào)用self.func(*args)失敗,因?yàn)镃實(shí)例參數(shù)無(wú)法傳遞 
class C: 
@decorator 
def method(self,x,y): 
...

這時(shí)候裝飾的方法重綁定到一個(gè)類(lèi)的方法上,而不是一個(gè)簡(jiǎn)單的函數(shù),這一點(diǎn)帶來(lái)的問(wèn)題是,當(dāng)裝飾器的方法__call__隨后運(yùn)行的時(shí)候,其中的self接受裝飾器類(lèi)實(shí)例,并且類(lèi)C的實(shí)例不會(huì)包含到一個(gè)*args中。

這時(shí)候,嵌套函數(shù)的替代方法工作得更好:

def decorator: 
def warpper(*args): 
# ... 
return wrapper 
@decorator 
def func(x,y): 
... 
func(6,7) 
class C: 
@decorator 
def method(self,x,y): 
... 
x = C() 
x.method(6,7)

類(lèi)裝飾器

類(lèi)裝飾器與函數(shù)裝飾器使用相同的語(yǔ)法和非常相似的編碼方式。類(lèi)裝飾器是管理類(lèi)的一種方式,或者用管理或擴(kuò)展類(lèi)所創(chuàng)建的實(shí)例的額外邏輯,來(lái)包裝實(shí)例構(gòu)建調(diào)用。

用法

假設(shè)類(lèi)裝飾器返回一個(gè)可調(diào)用對(duì)象的一個(gè)單參數(shù)的函數(shù),類(lèi)裝飾器的語(yǔ)法為:

@decorator 
class C: 
... 
x = C(99)

等同于下面的語(yǔ)法:

class C: 
... 
C = decorator(C) 
x = C(99)

直接效果是隨后調(diào)用類(lèi)名會(huì)創(chuàng)建一個(gè)實(shí)例,該實(shí)例會(huì)觸發(fā)裝飾器所返回的可調(diào)用對(duì)象,而不是調(diào)用最初的類(lèi)自身。

實(shí)現(xiàn)

類(lèi)裝飾器返回的可調(diào)用對(duì)象,通常創(chuàng)建并返回最初的類(lèi)的一個(gè)新的實(shí)例,以某種方式來(lái)擴(kuò)展對(duì)其接口的管理。例如,下面的實(shí)例插入一個(gè)對(duì)象來(lái)攔截一個(gè)類(lèi)實(shí)例的未定義的屬性:

def decorator(cls): 
class Wrapper: 
def __init__(self,*args): 
self.wrapped = cls(*args) 
def __getattr__(self,name): 
return getattr(self.wrapped,name) 
return Wrapper 
@decorator 
class C: # C = decorator(C) 
def __init__(self,x,y): # Run by Wrapper.__init__ 
self.attr = 'spam' 
x = C(6,7) # 等價(jià)于Wrapper(6,7) 
print(x.attr)

在這個(gè)例子中,裝飾器把類(lèi)的名稱(chēng)重新綁定到另一個(gè)類(lèi),這個(gè)類(lèi)在一個(gè)封閉的作用域中保持了最初的類(lèi)。

就像函數(shù)裝飾器一樣,類(lèi)裝飾器通??梢跃帉?xiě)為一個(gè)創(chuàng)建并返回可調(diào)用對(duì)象的“工廠(chǎng)”函數(shù)。

裝飾器嵌套

有時(shí)候,一個(gè)裝飾器不夠,裝飾器語(yǔ)法允許我們向一個(gè)裝飾器的函數(shù)或方法添加包裝器邏輯的多個(gè)層。這種形式的裝飾器的語(yǔ)法為:

@A 
@B 
@C 
def f(...): 
...

如下這樣轉(zhuǎn)換:

def f(...): 
... 
f = A(B(C(f))) 

這里,最初的函數(shù)通過(guò)3個(gè)不同的裝飾器傳遞,每個(gè)裝飾器處理前一個(gè)結(jié)果。

裝飾器參數(shù)

函數(shù)裝飾器和類(lèi)裝飾器都能接受參數(shù),如下:

@decorator(A,B) 
def F(arg): 
... 
F(99)

自動(dòng)映射到其對(duì)等形式:

def F(arg): 
... 
F = decorator(A,B)(F) 
F(99)

裝飾器參數(shù)在裝飾之前就解析了,并且它們通常用來(lái)保持狀態(tài)信息供隨后的調(diào)用使用。例如,這個(gè)例子中的裝飾器函數(shù),可能采用如下形式:

def decorator(A,B): 
# 保存或使用A和B 
def actualDecorator(F): 
# 保存或使用函數(shù) F 
# 返回一個(gè)可調(diào)用對(duì)象 
return callable 
return actualDecorator

以上,這是裝飾器的基礎(chǔ)知識(shí),接下來(lái)將學(xué)習(xí)編寫(xiě)自己的裝飾器。

相關(guān)文章

  • python讀取并定位excel數(shù)據(jù)坐標(biāo)系詳解

    python讀取并定位excel數(shù)據(jù)坐標(biāo)系詳解

    這篇文章主要介紹了python讀取并定位excel數(shù)據(jù)坐標(biāo)系詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-06-06
  • Python利用PyMuPDF實(shí)現(xiàn)PDF文件處理

    Python利用PyMuPDF實(shí)現(xiàn)PDF文件處理

    PyMuPDF是MuPDF的Python綁定-“輕量級(jí)PDF和XPS查看器”。本文將利用PyMuPDF實(shí)現(xiàn)PDF的一些基本操作,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2022-05-05
  • Gauss-Seidel迭代算法的Python實(shí)現(xiàn)詳解

    Gauss-Seidel迭代算法的Python實(shí)現(xiàn)詳解

    這篇文章主要介紹了Gauss-Seidel迭代算法的Python實(shí)現(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-06-06
  • python使用logging模塊記錄日志的操作

    python使用logging模塊記錄日志的操作

    在編寫(xiě)?Python?程序時(shí),日志記錄是一個(gè)非常重要的部分,日志不僅幫助你在開(kāi)發(fā)過(guò)程中調(diào)試代碼,還可以在程序正式運(yùn)行時(shí)提供診斷信息,幫助定位問(wèn)題,在本文中,我們將介紹?Python?的?logging?模塊,幫助你了解如何使用這個(gè)模塊來(lái)記錄和管理日志,需要的朋友可以參考下
    2024-10-10
  • python的pandas工具包,保存.csv文件時(shí)不要表頭的實(shí)例

    python的pandas工具包,保存.csv文件時(shí)不要表頭的實(shí)例

    今天小編小編就為大家分享一篇python的pandas工具包,保存.csv文件時(shí)不要表頭的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-06-06
  • Python?運(yùn)行?shell?命令的方法匯總

    Python?運(yùn)行?shell?命令的方法匯總

    這篇文章主要介紹了Python運(yùn)行shell命令的一些方法,我們來(lái)看一下 python 中有哪些自帶模塊或者方法可以實(shí)現(xiàn),對(duì)Python運(yùn)行shell命令感興趣的朋友跟隨小編一起看看吧
    2023-07-07
  • Python進(jìn)程間的通信一起來(lái)了解下

    Python進(jìn)程間的通信一起來(lái)了解下

    這篇文章主要為大家詳細(xì)介紹了Python進(jìn)程間通信,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • python如何實(shí)現(xiàn)多層級(jí)自動(dòng)賦值字典

    python如何實(shí)現(xiàn)多層級(jí)自動(dòng)賦值字典

    這篇文章主要介紹了python如何實(shí)現(xiàn)多層級(jí)自動(dòng)賦值字典問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • matplotlib 生成的圖像中無(wú)法顯示中文字符的解決方法

    matplotlib 生成的圖像中無(wú)法顯示中文字符的解決方法

    這篇文章主要介紹了matplotlib 生成的圖像中無(wú)法顯示中文字符的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • pyside6-uic生成py代碼中文為unicode(亂碼)的問(wèn)題解決方案

    pyside6-uic生成py代碼中文為unicode(亂碼)的問(wèn)題解決方案

    這篇文章主要介紹了如何解決pyside6-uic生成py代碼中文為unicode(亂碼)的問(wèn)題,文中通過(guò)代碼和圖文介紹的非常詳細(xì),對(duì)大家解決問(wèn)題有一定的幫助,需要的朋友可以參考下
    2024-02-02

最新評(píng)論

瓦房店市| 宝清县| 渭南市| 琼结县| 铜陵市| 扎鲁特旗| 无为县| 成安县| 百色市| 张家口市| 霍邱县| 郸城县| 伽师县| 平安县| 贵阳市| 蓝山县| 襄城县| 泸州市| 开封市| 建水县| 扎囊县| 平舆县| 牙克石市| 栾城县| 昌都县| 大渡口区| 略阳县| 马龙县| 呼图壁县| 子长县| 诸城市| 寿阳县| 鹿泉市| 商城县| 勃利县| 崇文区| 获嘉县| 合作市| 滁州市| 定安县| 北川|