有一個函數say
def say():
return "Hello"
現在需要得到下面的結果
'<b>Hello</b>'
一般可能會這樣做
def makebold(string):
return "<b>"+string+"</b>"
print makebold(say())
這樣的嵌套用多了會讓代碼看起來很雜亂,並且在某些特別的情況下,如django的view中,我不能把view放到一個函數裡來執行,這樣的就可以使用裝飾器來實現這個結果。
裝飾器函數
import functools
def makebold(func):
@functools.wraps(func)
def wrapper(*args):
return "<b>" + func(*args) + "</b>"
return wrapper
給hello函數加上裝飾器
@makebold
def hello():
return "Hello"
只需要調用hello就能實現在嵌套的效果
hello() ## 返回 '<b>Hello</b>'
如果我現在不要固定只在輸出外面加<b>標簽,需要給參數來決定外面的標簽
def makestyle(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args):
return '<%s>%s</%s>' % (text, func(*args) , text)
return wrapper
return decorator
帶參數的裝飾器
@makestyle('i')
def hello():
return "Hello World"
調用hello函數
hello() ## 返回 '<i>Hello</i>'
帶參數的裝飾器的執行相當於
print makestyle('i')(hello)
先執行makestyle(‘i’),返回decorator函數,再調用decorator函數,參數是hello函數,最終返回wrapper函數。
因為最後返回的是wrapper函數,函數名字是’wrapper’,所以需要用Python內置的functools.wraps來把原始函數的__name__等屬性復制到wrapper()函數中,不然有些依賴函數簽名的代碼執行就會出錯了。