隨記,保留函數(shù)元信息

@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)容。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容