@wraps 裝飾器
我們平時(shí)寫(xiě)函數(shù)的時(shí)候,可能會(huì)在原函數(shù)的基礎(chǔ)上增加額外的處理,比較常見(jiàn)的如:日志,計(jì)時(shí)等。
這里就是我們之前提及的裝飾器的運(yùn)用。關(guān)于裝飾器的簡(jiǎn)單使用,具體可查看下面的文章進(jìn)行了解:
Python 裝飾器
今天,篇幅不提及過(guò)多關(guān)于裝飾器如何使用,主要說(shuō)明一下,當(dāng)裝飾器作用在函數(shù)上,如何保留原函數(shù)的元信息。
在這里,需要用到 functools 庫(kù)中 @wraps 裝飾器來(lái)對(duì)底層包裝函數(shù)進(jìn)行注解。先編寫(xiě)一個(gè)計(jì)時(shí)的裝飾器,示例代碼如下:
# 計(jì)時(shí)裝飾器
import time
from functools import wraps
def timeit(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(func.__name__, end - start)
return res
return wrapper
現(xiàn)在使用上面的裝飾器來(lái)裝飾一個(gè)簡(jiǎn)單的計(jì)算函數(shù),并檢查函數(shù)的元信息:
In [11]: @timeit
...: def count(n:int):
...: """simple cacl
...: """
...: while n > 0:
...: n -= 1
...: print("complete!")
...:
In [12]: count(1000000)
complete!
count 0.04680013656616211
In [17]: count.__annotations__
Out[17]: {'n': int}
In [18]: count.__name__
Out[18]: 'count'
In [19]: count.__doc__
Out[19]: 'simple cacl\n '
在這里,可以看到,當(dāng)我們使用 @wraps 后,被裝飾函數(shù)的元信息能夠保留下。對(duì)比下,若是沒(méi)有使用 @wraps 結(jié)果會(huì)怎樣:
In [22]: count.__annotations__
Out[22]: {}
In [23]: count.__name__
Out[23]: 'wrapper'
In [24]: count.__doc__
此時(shí),被裝飾的函數(shù)的元信息則全部丟失了。如果希望保留被裝飾函數(shù)的元信息,那么建議使用 @wraps 復(fù)制元信息。
使用 @wraps 還能夠通過(guò) __wrapped__ 去直接訪(fǎng)問(wèn)被裝飾的函數(shù):
In [27]: count.__wrapped__(1000000)
complete!
這里直接訪(fǎng)問(wèn)被裝飾函數(shù),只打印出被裝飾函數(shù)的輸入語(yǔ)句 complete!,并沒(méi)有輸出計(jì)時(shí)的結(jié)果。
以上就是關(guān)于 @wraps 保留函數(shù)元信息的內(nèi)容。