Python:淺談裝飾器

Python的裝飾器是個(gè)好東西,它能干很多事情。但對(duì)于新手,它看起來(lái)似乎沒那么簡(jiǎn)單。
但事實(shí)上,裝飾器本身也只是個(gè)函數(shù)。

import time
def log(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print("The func '{}' used {}s.".format(func.__name__, end-start))
        return result
    return warpper

這一個(gè)裝飾器,當(dāng)我們這樣使用時(shí)

@log
def fuck(name):
    """Fuck someone"""
    print("Fuck", name)

它只是執(zhí)行了fuck = log(fuck)這樣一句代碼而已。
也就是說,我們表面上是用fuck("myself"),事實(shí)上執(zhí)行的都是log(fuck)("myself")。因?yàn)镻ython里面都是對(duì)象嘛。
同樣的道理,假設(shè)我們定義了一個(gè)帶參數(shù)的裝飾器logging,它實(shí)際上執(zhí)行的是

func = logging(arguments)(func)

也就是上面那個(gè)不帶參數(shù)的裝飾器多定義一層就行了。

import time
def logging(arguments):
    def log(func):
        def warpper(*args, **kwargs):
            start = time.time()
            result = func(*args, **kwargs)
            end = time.time()
            print("The func '{}' used {}s.".format(func.__name__, end-start))
            return result
        return warpper
    # do something
    return log

但,當(dāng)我們使用一個(gè)裝飾器之后,它會(huì)將原本的函數(shù)元信息給覆蓋掉。譬如:函數(shù)名稱,函數(shù)文檔等等。
例如上例

print(fuck.__name__)
print(fuck.__doc__)

你會(huì)發(fā)現(xiàn),函數(shù)信息全部沒了!fuck它不叫fuck,改名叫wrapper了。它的文檔也變成了none
解決辦法很簡(jiǎn)單,定義裝飾器的時(shí)候用warps裝飾器裝飾接受原函數(shù)參數(shù)的那一層就行了。
這個(gè)來(lái)自functools模塊的裝飾器能幫你復(fù)制函數(shù)的元信息到被綁定的函數(shù)身上。

修改裝飾器如下(其實(shí)就加了一行代碼hhh)

import time
from functools import wraps
def log(func):
    @wraps(func)
    def warpper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print("The func '{}' used {}s.".format(func.__name__, end-start))
        return result
    return warpper

當(dāng)我們?cè)龠\(yùn)行

print(fuck.__name__)
print(fuck.__doc__)

就能看到函數(shù)的的元信息沒變了。

  • 裝飾器定義時(shí)加@wraps是個(gè)好習(xí)慣。

一個(gè)較為實(shí)用的裝飾器demo在該專題的另一篇文章:函數(shù)參數(shù)類型檢查

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 要點(diǎn): 函數(shù)式編程:注意不是“函數(shù)編程”,多了一個(gè)“式” 模塊:如何使用模塊 面向?qū)ο缶幊蹋好嫦驅(qū)ο蟮母拍?、屬性?..
    victorsungo閱讀 1,697評(píng)論 0 6
  • Python進(jìn)階框架 希望大家喜歡,點(diǎn)贊哦首先感謝廖雪峰老師對(duì)于該課程的講解 一、函數(shù)式編程 1.1 函數(shù)式編程簡(jiǎn)...
    Gaolex閱讀 5,991評(píng)論 6 53
  • 記者:胡知奐 整個(gè)春運(yùn)期間,北京地面公交會(huì)達(dá)到2.94億人次,為了應(yīng)對(duì)這樣的大客流,北京公交集團(tuán)在北京站、北京西站...
    視野聚焦閱讀 361評(píng)論 0 1
  • 我曾經(jīng)喜歡過我的同桌,我唯一承認(rèn)過并且不后悔的喜歡過。 那是我碌碌無(wú)為的青春年華里寥寥可數(shù)的回憶,因?yàn)榇蠖鄶?shù)時(shí)間我...
    胡加加閱讀 377評(píng)論 1 2
  • 不行萬(wàn)里,何以仰泰山
    一任風(fēng)塵閱讀 149評(píng)論 0 0

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