Python 裝飾器筆記

本文案例內容參考自:https://www.liaoxuefeng.com/wiki/1016959663602400/1017451662295584

裝飾器概念

當我們想爲現有的函數增加額外功能,但又不想改變這個函數內部的代碼,那麼我們可以通過爲該函數添加“裝飾器”的形式來實現額外功能。

裝飾器簡例

例如目前我們現在有一個打印時間字符串的函數:

def timestr():
    print("2020-06-03")

當我們執行時,該函數只會打印一個時間字符串,現在我們想在執行該函數時可以額外打印該函數的名字,便可以定義如下“裝飾器”函數:

def log(func):
    def wrapper(*args,**kw):
        print(f"func name is {func.__name__}")
        return func(*args,**kw)
    return wrapper

定義完裝飾器,使用裝飾器的格式如下:

@log
def timestr():
    print("2020-06-03")

這樣,當我們直接執行 timestr() 時,便會得到如下結果:

func name is timestr
2020-06-03

裝飾器在這裏就實現了打印函數名稱的額外功能。這裏 @log 相當於執行了 timestr = log(timestr),此時如果再打印修飾器修飾過的 timestr 函數名稱,會發現其變成了 wrapper:

print(timestr.__name__)
# 'wrapper'

這就需要把原始函數的名稱等屬性同步複製到 wrapper() 函數中,否則有些依賴函數簽名的代碼執行就會出錯。

這裏就需要 Python 內置的 functools.wraps 來實現同步相關屬性,最終裝飾器完整版代碼如下:

import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args,**kw):
        print(f"func name is {func.__name__}")
        return func(*args,**kw)
    return wrapper

@log
def timestr():
    print("2020-06-03")

這樣再次打印 timestr 的函數名時,就會同步爲原函數名 ‘timestr’。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章