python装饰器副作用_对Python 装饰器的理解心得
0x00000000030A40D0位置(這個位置應(yīng)該是指內(nèi)存位置)存有一個function(方法)叫target;在 target后面加上(),表示調(diào)用該方法,即輸入target(),“大腦”便按照target方法所寫的代 碼逐條執(zhí)行,于是打印出了target字符串,并且“大腦”明白在0x00000000030A4268位置有一 個叫returnme的方法;因為target對象調(diào)用后是會返回一個returnme方法,并且方法是可以被調(diào)用的,因 此你可以直接這樣書寫target()(),“大腦”會逐條執(zhí)行target中的代碼,然后return一個 returnme,因為多加了一個(),表示要對返回的returnme進(jìn)行調(diào)用,于是再次逐條執(zhí)行returnme中的代碼 ,最后便能看到15、16的打印結(jié)果;而returnme方法是沒有返回任何可調(diào)用的對象,因此當(dāng)輸入 returnme()()時,“大腦”會報錯。
下面我們可以來解釋一下腳本2和腳本3的運(yùn)行詳情,之前說過,裝飾器的工作原理就是腳本1代碼所演 示的那樣。
@decorator
def target():
...
等同于
def decorator(target)():
...
注:python語法中以上寫法是非法的,以上只是為了便于理解。
當(dāng)你調(diào)用被裝飾方法target時,其實首先被執(zhí)行的是作為裝飾器的decorator函數(shù),然后“大腦 ”會把target方法作為參數(shù)傳進(jìn)去,于是:
#腳本2
def decorator(func):
func()
print('this is decorator')
@decorator
def target():
print('this is target')
target
-------------------------------------------
實際運(yùn)行情況:
首先調(diào)用decorator方法:decorator()
因為decorator方法含1個參數(shù),因此將target傳入:decorator(target)
運(yùn)行代碼“func()”,根據(jù)傳入的參數(shù),實際執(zhí)行target(),結(jié)果打印出:this is target
運(yùn)行代碼"print('this is decorator')",結(jié)果打印出:this is decorator
對比腳本3的運(yùn)行情況:
#腳本3
def decorator(func):
func()
print('this is decorator')
@decorator
def target():
print('this is target')
target()
-------------------------------------------
實際運(yùn)行情況:
首先調(diào)用decorator方法:decorator()
因為decorator方法含1個參數(shù),因此將target傳入:decorator(target)
運(yùn)行代碼“func()”,根據(jù)傳入的參數(shù),實際執(zhí)行target(),結(jié)果打印出:this is target
運(yùn)行代碼"print('this is decorator')",結(jié)果打印出:this is decorator
以上與腳本2中運(yùn)行情況完全相同,接下來便是執(zhí)行腳本2中target沒有的(),也就是執(zhí)行調(diào)用命令。
由于decorator(target)沒有返回一個可以被調(diào)用的對象,因此“大腦”提示錯
誤:'NoneType' object is not callable
如果你還不是很清楚,請看下面的等價關(guān)系:
@decorator
def target():
...
等同于
def decorator(target)():
...
因此:
target == decorator(target)
target() == decorator(target)()
所以:
假設(shè)有一個變量var=target,在將target賦值給var時,其實是將decorator(target)的調(diào)用結(jié)果賦值給
var,因為var不具備調(diào)用性(not callable),因此執(zhí)行var()時,編譯器會報錯它是個NoneType對象,
不能調(diào)用。
綜上所述,你大概已經(jīng)能夠明白所謂的裝飾器是怎么一回事,它是怎么工作的。但腳本2和腳本3中的 寫法會帶來一些困惑,這個困惑就是通過我們編寫的decorator裝飾器對target進(jìn)行裝飾后,將target變 成了一個永遠(yuǎn)不能被調(diào)用的方法,或者說變成了一個調(diào)用就報錯的方法。這跟我們的使用習(xí)慣以及對方法 的認(rèn)識是很不協(xié)調(diào)的,畢竟我們還是習(xí)慣一個方法天生注定可以被調(diào)用這種看法。所以為了滿足我們對方 法的定義,我們最好將作為裝飾器的方法寫成一個可以返回具有被調(diào)用能力的對象的方法。
#腳本4
def whatever():
print('this is whatever')
def decorator(func):
func()
print('this is decorator')
return whatever #1
@decorator
def target():
print('this is target')
------------------------------
輸入:target
結(jié)果:
this is target
this is decorator
輸入:target()
結(jié)果:
this is target
this is decorator
this is whatever
在#1的位置,你可以return任何可以被調(diào)用的方法或類,甚至你可以直接寫成:
def whatever():
print('this is whatever')
def decorator(func):
return whatever
總結(jié)
以上是生活随笔為你收集整理的python装饰器副作用_对Python 装饰器的理解心得的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python分类预测降低准确率_pyth
- 下一篇: python博弈论代码_使用 40 多行