參考:https://www.liaoxuefeng.com/wiki/1016959663602400/1017451662295584
Python萬物皆對象,函數也是一個對象,也可以賦值給變量,所以通過變量也能夠調用該函數。
假設要增強函數的功能,比如在函數調用前后自動打印日志,但又不希望修改函數的定義,這種在代碼運行期間動態增加功能的方式,稱之為“裝飾器”。本質上,裝飾器就是一個返回函數的高階函數。
由於log()是一個裝飾器,返回一個函數,所以,原來的now()函數仍然存在,只是現在同名的now變量指向了新的函數,於是調用now()將執行新函數,即在log()函數中返回的wrapper()函數。
如果要實現可以接受任意參數調用的函數,wrapper的參數設置為*arg,**kw。
如果裝飾器本身需要傳入參數,那就需要編寫一個返回裝飾器的高階函數。
1 #不需要編寫wrapper.__name__=func.__name__這樣的代碼,Python內#置的functools.wraps就是干這個事的,所以,一個完整的decorator的寫法#如下 2 import functools 3 def log(now): 4 @functools.wraps(func) 5 def wrapper(*args, **kw): 6 print('call %s():' % func.__name__) 7 return func(*args, **kw) 8 return wrapper
1 #針對帶參數的裝飾器 2 import functools 3 def log(text): 4 def decorator(func): 5 @functools.wraps(func) 6 def wrapper(*args, **kw): 7 print('%s %s():' % (text, func.__name__)) 8 return func(*args, **kw) 9 return wrapper 10 return decorator
裝飾器准備:作用就是為其他函數增加功能,開放封閉原則。
1.作用域:作用域查找過程 局部作用域-->嵌套作用域-->全局作用域-->內置變量
2.高階函數:函數名作為參數輸入或者函數名作為返回值
函數名作為參數輸入-->可以實現在不修改源代碼的情況下添加功能
函數名作為返回值-->可以實現不修改調用方式
3.閉包:如果在一個內部函數里,對在外部作用域(但不是在全局作用域)的變量進行引用,那么內部函數就被認為是閉包
閉包=函數塊(內部函數)+ 定義函數時的環境
裝飾器示例:
如果要實現可以裝飾具有任何參數的函數的裝飾器怎么辦? python-->*args **args