應用場景:
1、授權(Authorization)
裝飾器能有助於檢查某個人是否被授權去使用一個web應用的端點(endpoint)。它們被大量使用於Flask和Django web框架中。這里是一個例子來使用基於裝飾器的授權:
from functools import wraps # 最新版python引用是 import functools def requires_auth(f): # f 就是我們需要裝飾的函數,一看就是不帶參數的裝飾器 @wraps(f) # 新版python寫法 @functools.wraps(f) def decorated(*args, **kwargs): auth = request.authorization if not auth or not check_auth(auth.username, auth.password): authenticate() return f(*args, **kwargs) return decorated # 該裝飾器需相關配置才能運行,這里是截取代碼展示應用
2.、日志(Logging)
日志是裝飾器運用的另一個亮點。這是個例子:
from functools import wraps def logit(func): @wraps(func) def with_logging(*args, **kwargs): print(func.__name__ + " was called") return func(*args, **kwargs) return with_logging @logit def addition_func(x): """Do some math.""" return x + x result = addition_func(4)
我敢肯定你已經在思考裝飾器的一個其他聰明用法了。
3.、帶參數的裝飾器
帶參數的裝飾器是典型的閉包函數
4.、在函數中嵌入裝飾器
我們回到日志的例子,並創建一個包裹函數,能讓我們指定一個用於輸出的日志文件。
from functools import wraps def logit(logfile='out.log'): def logging_decorator(func): @wraps(func) def wrapped_function(*args, **kwargs): log_string = func.__name__ + " was called" print(log_string) # 打開logfile,並寫入內容 with open(logfile, 'a') as opened_file: # 現在將日志打到指定的logfile opened_file.write(log_string + '\n') return func(*args, **kwargs) return wrapped_function return logging_decorator @logit() def myfunc1(): pass myfunc1() # Output: myfunc1 was called # 現在一個叫做 out.log 的文件出現了,里面的內容就是上面的字符串 @logit(logfile='func2.log') def myfunc2(): pass myfunc2() # Output: myfunc2 was called # 現在一個叫做 func2.log 的文件出現了,里面的內容就是上面的字符串
5.、裝飾器類
現在我們有了能用於正式環境的logit裝飾器,但當我們的應用的某些部分還比較脆弱時,異常也許是需要更緊急關注的事情。比方說有時你只想打日志到一個文件。而有時你想把引起你注意的問題發送到一個email,同時也保留日志,留個記錄。這是一個使用繼承的場景,但目前為止我們只看到過用來構建裝飾器的函數。
幸運的是,類也可以用來構建裝飾器。那我們現在以一個類而不是一個函數的方式,來重新構建logit。