1. python 裝飾器
1) 2層裝飾器
def decorator(func): # TODO def wrapper(*args, **kwargs): # TODO func(*args, **kwargs) # TODO # TODO return wrapper
2) 3層裝飾器
def decorator3(a=0, b=0): # TODO def wrapper(func): # TODO def inner_wrapper(*args, **kwargs): # TODO func(*args, **kwargs) # TODO # TODO return inner_wrapper # TODO return wrapper
此處a,b可為任意指定參數,但不可以更改。
3) 類裝飾器, python中類本身是不可調用的, 需要實現__call__方法, 將類變為callable。
class decorator(object): def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): # TODO self.func(*args, **kwargs) # TODO
class decorator2(object): def __call__(self, func): # TODO def wrapper(*args, **kwargs): # todo func(*args, **kwargs) # todo # TODO return wrapper
python裝飾器使用閉包的方式提供aop的概念。不過需要注意,裝飾器裝飾的函數,無法通過func.__name__獲得真正的函數名, 可以導入functools.wraps包裝。
wraps實際上調用的update_wrapper。
2. python裝飾器的執行順序。
1 import time 2 3 4 def log(level="info"): 5 print "log" 6 7 def wrapper(f): 8 print "wrapper start" 9 10 def inner_wrapper(*args, **kwargs): 11 print "inner_wrapper start" 12 print "{0}: {1}".format(level, time.time()) 13 f(*args, **kwargs) 14 print "{0}: {1}".format(level, time.time()) 15 print "inner_wrapper end" 16 17 print "wrapper end" 18 return inner_wrapper 19 20 print "end" 21 return wrapper 22 23 24 def log2(f): 25 print "log2..." 26 27 def wrapper(*args, **kwargs): 28 print "log2" 29 f(*args, **kwargs) 30 print "log2" 31 32 print "log2..." 33 return wrapper 34 35 36 @log2 37 @log(level="debug") 38 def test(a, b): 39 print a, b
執行test,輸出
參見:https://segmentfault.com/a/1190000007837364
多個裝飾器是按從下到上的順序執行的, 在上圖的例子中,test可以簡化為test=log2(log(test)), 先執行log裝飾器inner_wrapper外層的,得到inner_wrapper, 此時inner_wrapper是log2, 得到log2的wrapper, 此wrapper封裝的func是log的inner_wrapper, 依次順序執行,
結果如上圖所示。