函數裝飾器

對於某個函數,若是但願在不改變函數代碼的前提下,爲該函數增長額外的功能,
那麼能夠使用裝飾器來裝飾該函數。閉包

裝飾器是一個函數,裝飾器接收一個函數做爲參數(傳入的實參是被裝飾的函數),
裝飾器的內部嵌套定義另外一個函數,內函數中會引用裝飾器的參數,而且裝飾器的返回值是內函數。
這樣構成了一個閉包。app

爲了讓內函數接收任意類型的參數,將內函數的形參定義爲(*args, **kwargs)。
在函數中首選完成爲被裝飾函數添加新功能,而後調用被裝飾的函數。函數

裝飾器的應用語法:
在被裝飾函數的前面添加:"@裝飾器的函數名"。spa

●爲add函數添加log功能。code

#執行流程:
1,被裝飾的函數add做爲實參傳遞給裝飾器log。
2,返回裝飾器的內函數wrapper。
3,將內函數wrapper賦值給名爲add(被裝飾函數的函數名)的變量。
4,再調用被裝飾函數add時,其實調用的是裝飾器的內函數wrapper。blog

 1 #add函數的裝飾器函數。
 2 def log(func):
 3     def wrapper(*args, **kwargs):
 4         print("函數%s被調用了" % func.__name__)
 5         return func(*args, **kwargs)
 6     return wrapper
 7 
 8 #添加標記@log,對函數add應用裝飾器。至關於調用了add = log(add)
 9 @log  
10 def add(sum1, sum2):
11     print(sum1, sum2)
12     return sum1 + sum2
13 
14 #調用方法和一般同樣。打印調用結果。
15 print(add(1, 2))
16 
17 #打印實際被調用的函數名。
18 print(add.__name__) #結果爲wrapper。

●實現被裝飾後,函數名依舊是add。class

在裝飾器的內函數前面添加另一個裝飾器:@functools.wraps(裝飾器的函數名),
functools.wraps爲標準庫模塊functools中的函數wraps。import

 1 import functools
 2 
 3 def log2(func):
 4     @functools.wraps(func)
 5     def wrapper(*args, **kwargs):
 6         print("函數%s被調用了" % func.__name__)
 7         return func(*args, **kwargs)
 8     return wrapper
 9 
10 @log2
11 def add2(sum1, sum2):
12     print(sum1, sum2)
13     return sum1 + sum2
14 
15 print(add2(1, 2))
16 
17 print(add2.__name__) #結果爲add2。

●給裝飾器傳遞額外參數。
須要3層嵌套裝飾器。
對於@log3('6月','18日'),至關於執行語句:add3 = log3('6月','18日')(add3)。變量

 1 def log3(month, day):
 2     def decorator(func):
 3         @functools.wraps(func)
 4         def wrapper(*args, **kwargs):
 5             print("%s%s, 函數%s被調用了" % (month, day, func.__name__))
 6             return func(*args, **kwargs)
 7         return wrapper
 8     return decorator
 9 
10 @log3('6月', '18日')
11 def add3(sum1, sum2):
12     print(sum1, sum2)
13     return sum1 + sum2
14 
15 print(add3(1, 2))
相關文章
相關標籤/搜索