裝飾器為python的語法糖(syntax candy),旨在簡化函式之間的相互呼叫,能透過簡單的@
就呼叫出事先編寫好的函式。
使用順序上則是遵循遞迴的(recursive)構造,會先將函式丟入離最近的裝飾器中,再將整體丟入更上層的裝飾器中。
裝飾器一旦被寫下,無論是否呼叫被裝飾的函式,裝飾器都會被執行,若不想執行裝飾器,則裝飾器最外層只能留下retuen
指令。
Tip
簡易的理解方式:擁有裝飾器的函式,會先執行裝飾器的內容,再執行原先函式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
def fun2(v):
def decorator(fun):
print('This is not a decorator.')
return fun
decorator(fun2)
#在語法糖中被@取代
print(v)
#以上等價於
def decorator(fun):
print('This is a decorator.')
return fun
@decorator
def fun3(v):
print(v)
if __name__ == "__main__":
f1 = fun2(5)
#>>>'This is not a decorator.'
#>>>5
f2 = fun3(5)
#>>>'This is a decorator.'
#>>>5
|
此外,裝飾器本身也能帶有參數。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
def decorator(text):
def decorator2(fun):
print('This is another decorator.')
return fun
print('This is a decorator.')
print(text)
return decorator2
@decorator('Hello')
def fun2(v):
print(v)
if __name__ == "__main__":
fun2(1)
#>>>This is a decorator.
#>>>Hello
#>>>This is another decorator.
#>>>1
|
若裝飾器需要裝飾多個函式,每個函式間的參數皆不同,則需要使用*args
、**kwargs
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
def decorator(fun):
def decorator2(*args, **kwargs):
print('This is a decorator.')
return fun(*args, **kwargs)
return decorator2
@decorator
def fun2(v):
print(v)
@decorator
def fun3(a, b, c):
print(a, b, c)
|
類別也能當作裝飾器使用
Reference