什么是裝飾器呢?
我的理解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>