Python中用Decorator來簡(jiǎn)化元編程的教程
少勞多得
Decorator 與 Python 之前引入的元編程抽象有著某些共同之處:即使沒有這些技術(shù),您也一樣可以實(shí)現(xiàn)它們所提供的功能。正如 Michele Simionato 和我在 可愛的 Python 專欄的早期文章 中指出的那樣,即使在 Python 1.5 中,也可以實(shí)現(xiàn) Python 類的創(chuàng)建,而不需要使用 “元類” 掛鉤。
Decorator 根本上的平庸與之非常類似。Decorator 所實(shí)現(xiàn)的功能就是修改緊接 Decorator 之后定義的函數(shù)和方法。這總是可能的,但這種功能主要是由 Python 2.2 中引入的 classmethod() 和 staticmethod() 內(nèi)置函數(shù)驅(qū)動(dòng)的。在舊式風(fēng)格中,您可以調(diào)用 classmethod(),如下所示:
清單 1. 典型的 “舊式” classmethod
class C: def foo(cls, y): print "classmethod", cls, y foo = classmethod(foo)
雖然 classmethod() 是內(nèi)置函數(shù),但并無獨(dú)特之處;您也可以使用自己的方法轉(zhuǎn)換函數(shù)。例如:
清單 2. 典型的 “舊式” 方法的轉(zhuǎn)換
def enhanced(meth): def new(self, y): print "I am enhanced" return meth(self, y) return new class C: def bar(self, x): print "some method says:", x bar = enhanced(bar)
decorator 所做的一切就是使您避免重復(fù)使用方法名,并且將 decorator 放在方法定義中第一處提及其名稱的地方。例如:
清單 3. 典型的 “舊式” classmethod
class C: @classmethod def foo(cls, y): print "classmethod", cls, y @enhanced def bar(self, x): print "some method says:", x
decorator 也可以用于正則函數(shù),采用的是與類中的方法相同的方式。令人驚奇的是,這一切是如此簡(jiǎn)單(嚴(yán)格來說,甚至有些不必要),只需要對(duì)語法進(jìn)行簡(jiǎn)單修改,所有東西就可以工作得更好,并且使得程序的論證更加輕松。通過在方法定義的函數(shù)之前列出多個(gè) decorator,即可將 decorator 鏈接在一起;良好的判斷可以有助于防止將過多 decorator 鏈接在一起,不過有時(shí)候?qū)讉€(gè) decorator 鏈接在一起是有意義的:
清單 4. 鏈接 decorator
@synchronized @logging def myfunc(arg1, arg2, ...): # ...do something # decorators are equivalent to ending with: # myfunc = synchronized(logging(myfunc)) # Nested in that declaration order
Decorator 只是一個(gè)語法糖,如果您過于急切,那么它就會(huì)使您搬起石頭砸了自己的腳。decorator 其實(shí)就是一個(gè)至少具有一個(gè)參數(shù)的函數(shù) —— 程序員要負(fù)責(zé)確保 decorator 的返回內(nèi)容仍然是一個(gè)有意義的函數(shù)或方法,并且實(shí)現(xiàn)了原函數(shù)為使連接有用而做的事情。例如,下面就是 decorator 兩個(gè)不正確的用法:
清單 5. 沒有返回函數(shù)的錯(cuò)誤 decorator
>>> def spamdef(fn): ... print "spam, spam, spam" ... >>> @spamdef ... def useful(a, b): ... print a**2 + b**2 ... spam, spam, spam >>> useful(3, 4) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: 'NoneType' object is not callable
decorator 可能會(huì)返回一個(gè)函數(shù),但這個(gè)函數(shù)與未修飾的函數(shù)之間不存在有意義的關(guān)聯(lián):
清單 6. 忽略傳入函數(shù)的 decorator
>>> def spamrun(fn): ... def sayspam(*args): ... print "spam, spam, spam" ... return sayspam ... >>> @spamrun ... def useful(a, b): ... print a**2 + b**2 ... >>> useful(3,4) spam, spam, spam
最后,一個(gè)表現(xiàn)更良好的 decorator 可以在某些方面增強(qiáng)或修改未修飾函數(shù)的操作:
清單 7. 修改未修飾函數(shù)行為的 decorator
>>> def addspam(fn): ... def new(*args): ... print "spam, spam, spam" ... return fn(*args) ... return new ... >>> @addspam ... def useful(a, b): ... print a**2 + b**2 ... >>> useful(3,4) spam, spam, spam 25
您可能會(huì)質(zhì)疑,useful() 到底有多么有用?addspam() 真的是那樣出色的增強(qiáng) 嗎?但這種機(jī)制至少符合您通常能在有用的 decorator 中看到的那種模式。
高級(jí)抽象簡(jiǎn)介
根據(jù)我的經(jīng)驗(yàn),元類應(yīng)用最多的場(chǎng)合就是在類實(shí)例化之后對(duì)類中的方法進(jìn)行修改。decorator 目前并不允許您修改類實(shí)例化本身,但是它們可以修改依附于類的方法。這并不能讓您在實(shí)例化過程中動(dòng)態(tài)添加或刪除方法或類屬性,但是它讓這些方法可以在運(yùn)行時(shí)根據(jù)環(huán)境的條件來變更其行為?,F(xiàn)在從技術(shù)上來說,decorator 是在運(yùn)行 class 語句時(shí)應(yīng)用的,對(duì)于頂級(jí)類來說,它更接近于 “編譯時(shí)” 而非 “運(yùn)行時(shí)”。但是安排 decorator 的運(yùn)行時(shí)決策與創(chuàng)建類工廠一樣簡(jiǎn)單。例如:
清單 8. 健壯但卻深度嵌套的 decorator
def arg_sayer(what): def what_sayer(meth): def new(self, *args, **kws): print what return meth(self, *args, **kws) return new return what_sayer
相關(guān)文章
Python腳本如何在bilibili中查找彈幕發(fā)送者
這篇文章主要介紹了如何在bilibili中查找彈幕發(fā)送者,本文給大家分享小編寫的一個(gè)python腳本來實(shí)現(xiàn)bilibili彈幕發(fā)送者,需要的朋友可以參考下2020-06-06python開發(fā)實(shí)時(shí)可視化儀表盤的示例
這篇文章主要介紹了python開發(fā)實(shí)時(shí)可視化儀表盤的示例,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下2021-05-05Pytorch中torch.nn.Softmax的dim參數(shù)用法說明
這篇文章主要介紹了Pytorch中torch.nn.Softmax的dim參數(shù)用法說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06python圖片處理庫(kù)Pillow實(shí)現(xiàn)簡(jiǎn)單PS功能
Python 屆處理圖片最強(qiáng)的庫(kù)是 PIL(Python Image Library),但由于該庫(kù)只支持 2.x 版本,在此基礎(chǔ)上做了擴(kuò)展,出了一個(gè)兼容 3.x 的版本也就是 Pillow,因此,我們今天要用的庫(kù)就是Pillow2021-11-11Python光學(xué)仿真wxpython透鏡演示系統(tǒng)框架
這篇文章主要為大家介紹了Python光學(xué)仿真UI界面的wxpython透鏡演示系統(tǒng)框架基本講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10Python編寫簡(jiǎn)單的HTML頁(yè)面合并腳本
這篇文章主要介紹了Python編寫簡(jiǎn)單的HTML頁(yè)面合并腳本的相關(guān)資料,需要的朋友可以參考下2016-07-07