W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
你寫了一個(gè)裝飾器作用在某個(gè)函數(shù)上,但是這個(gè)函數(shù)的重要的元信息比如名字、文檔字符串、注解和參數(shù)簽名都丟失了。
任何時(shí)候你定義裝飾器的時(shí)候,都應(yīng)該使用 functools
庫(kù)中的 @wraps
裝飾器來(lái)注解底層包裝函數(shù)。例如:
import time
from functools import wraps
def timethis(func):
'''
Decorator that reports the execution time.
'''
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__, end-start)
return result
return wrapper
下面我們使用這個(gè)被包裝后的函數(shù)并檢查它的元信息:
>>> @timethis
... def countdown(n:int):
... '''
... Counts down
... '''
... while n > 0:
... n -= 1
...
>>> countdown(100000)
countdown 0.008917808532714844
>>> countdown.__name__
'countdown'
>>> countdown.__doc__
'\n\tCounts down\n\t'
>>> countdown.__annotations__
{'n': <class 'int'>}
>>>
在編寫裝飾器的時(shí)候復(fù)制元信息是一個(gè)非常重要的部分。如果你忘記了使用 @wrap
,那么你會(huì)發(fā)現(xiàn)被裝飾函數(shù)丟失了所有有用的信息。比如如果忽略 @wrap
后的效果是下面這樣的:
>>> countdown.__name__
'wrapper'
>>> countdown.__doc__
>>> countdown.__annotations__
{}
>>>
@wraps
有一個(gè)重要特征是它能讓你通過(guò)屬性 __wrapped__
直接訪問(wèn)被包裝函數(shù)。例如:
>>> countdown.__wrapped__(100000)
>>>
__wrapped__
屬性還能讓被裝飾函數(shù)正確暴露底層的參數(shù)簽名信息。例如:
>>> from inspect import signature
>>> print(signature(countdown))
(n:int)
>>>
一個(gè)很普遍的問(wèn)題是怎樣讓裝飾器去直接復(fù)制原始函數(shù)的參數(shù)簽名信息,如果想自己手動(dòng)實(shí)現(xiàn)的話需要做大量的工作,最好就簡(jiǎn)單的使用 __wrapped__
裝飾器。通過(guò)底層的 __wrapped__
屬性訪問(wèn)到函數(shù)簽名信息。更多關(guān)于簽名的內(nèi)容可以參考9.16小節(jié)。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: