python裝飾器學習總結

什么是裝飾器呢?

我的理解python中的裝飾器就是對一個函數(shù)調(diào)用前后增加一些新的代碼。

裝飾器是一個函數(shù),但是它里面重新定義了一個新的函數(shù),這個新的函數(shù)里面包含對一個指定函數(shù)的調(diào)用。最終裝飾器返回這個函數(shù)的引用。當然裝飾器不僅可以作用于一個函數(shù),也可以作用于一個類。

舉一個簡單的裝飾器的例子

def log_func_name(func):
    '''打印函數(shù)名'''
    def wrapper(*args, **kwargs):
        print('函數(shù){}正在運行'.format(func.__name__))
        func(*args, **kwargs)
    return wrapper

@log_func_name
def say_hello(cnt):
    '''打印hello'''
    for _ in range(cnt):
        print('hello')

if __name__ == '__main__':
    say_hello(3)

其實@log_func_name的語法糖,相當于在函數(shù)聲明后加上say_hello = log_func_name(say_hello)語句。
所以上面的代碼可以等價為

def log_func_name(func):
    '''打印函數(shù)名'''
    def wrapper(*args, **kwargs):
        print('函數(shù){}正在運行'.format(func.__name__))
        func(*args, **kwargs)
    return wrapper

def say_hello(cnt):
    '''打印hello'''
    for _ in range(cnt):
        print('hello')
say_hello = log_func_name(say_hello)

if __name__ == '__main__':
    say_hello(3)

如果上述代碼在ipython等交互環(huán)境上運行,我們還可以運行

say_hello.__name__
# 輸出 'wrapper'

由此可以看書say_hello函數(shù)并不是我們直接聲明的say_hello函數(shù),實際上say_hello指向log_lineno函數(shù)返回的wrapper函數(shù)。即上文所說,@log_func_name相當于執(zhí)行了say_hello = log_lineno(say_hello)這句命令。

問題來了,如果say_hello函數(shù)帶有參數(shù)那該怎么辦?因為say_hello其實是指向wrapper的,所以say_hello能接受的參數(shù),wrapper也必須能接受。那么對應say_hello函數(shù)的裝飾器函數(shù)代碼要如下所示

def log_func_name(func):
    '''打印函數(shù)名'''
    def wrapper(cnt):
        print('函數(shù){}正在運行'.format(func.__name__))
        func(cnt)
    return wrapper

@log_func_name
def say_hello(cnt):
    '''打印hello'''
    for _ in range(cnt):
        print('hello')

上述方法是最簡單粗暴的方法,即保持wrapper函數(shù)和say_hello函數(shù)的參數(shù)一致。
這樣問題就來了,一個裝飾器不可能只用于一個函數(shù)啊,不然直接在那個函數(shù)上修改就完事了。
即裝飾器的使用范圍要有廣泛性,比如log_func_name這個裝飾器是用于打印函數(shù)名,這個裝飾器對所有的函數(shù)都生效,不管函數(shù)多復雜。

這個時候就要用到*args**kwargs,要想知道這兩個參數(shù)有什么,收到運行下面代碼就知道啦

def print_args(*args, **kwargs):
    print(args)
    print(kwargs)

print_args(1,2,3)
# (1, 2, 3)
# {}
print_args(1,2,3,a=1,b=2)
# (1, 2, 3)
# {'a': 1, 'b': 2, 'c': 3}

可以看書,args就是一個參數(shù)的數(shù)組,kwargs是一個以參數(shù)名作為key的字典(關鍵字參數(shù)的字典)
*args前面的*用于將args數(shù)組解包,即傳入的不是args數(shù)組,而是將args數(shù)組里面的元素都當成參數(shù)傳用。同理**用于將字典解包。
這樣我們就解決了裝飾器的適用性問題了,開心?。?/p>

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

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

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