The only constraint on the result of a decorator is that it be callable, so it can
properly replace the decorated function.
decorator唯一限制是它必須是callable的,所以如果class作為decorator必須實現__call__方法使其成為callable的對象,而函數本身就是callable的。
用class做decorator
1 class my_decorator(object):
2 def __init__(self, f):
3 print("inside my_decorator.__init__()")
4 f() # Prove that function definition has completed
5 def __call__(self):
6 print("inside my_decorator.__call__()")
7 @my_decorator
8 def aFunction():
9 print("inside aFunction()")
10 print("Finished decorating aFunction()")
11 aFunction()
輸出:
inside my_decorator.__init__()
inside aFunction()
Finished decorating aFunction()
inside my_decorator.__call__()
如何解釋這個輸出,關鍵在於decorator程式的閱讀要從程式執行順序來理解,把decorator當成一次函數調用。
當程式從上至下執行到第7行時,my_decorator開始初始化,它以aFunction作為參數,傳入__init__()執行,然後__call__將原函數替換,執行第10行代碼,最後調用aFunction,因為這時原函數調用時,調用的是decorator替換後的callable對象,也就是__call__方法,所以執行的實際上是__call__。
函數作為decorator
1 def entry_exit(f):
2 def new_f():
3 print("Entering", f.__name__)
4 f()
5 print("Exited", f.__name__)
6 return new_f
7
8 @entry_exit
9 def func1():
10 print("inside func1()")
11
12 @entry_exit
13 def func2():
14 print("inside func2()")
15
16 func1()
17 func2()
同樣,程式執行到第8行,調用entry_exit將func1當參數傳入執行,返回new_f替換原函數,對func2同樣處理,最後調用func1和func2時實際上調用的就是替換了以後的函數。
所以decorator從根本上是函數指標的替換,用一個callable的對象替換原來的函數。