裝飾器是python中用于擴展函數或類功能的語法糖,本質是接收函數或類并返回新函數或類的可調用對象。1. 裝飾器通過@符號應用,如@my_decorator裝飾函數等價于將函數傳遞給裝飾器函數并替換原函數;2. 常見用途包括記錄日志/執行時間、權限控制、多層裝飾器疊加使用,例如log_time裝飾器可統一為函數添加耗時統計;3. 多個裝飾器按從下往上的順序依次執行,最靠近函數的裝飾器最先被調用;4. 類也可作為裝飾器,需實現__call__方法,適合需要維護狀態的場景,如緩存結果或計數器。
在python中,@decorator 是一種非常實用的語法糖,用來簡化函數或類的裝飾過程。簡單來說,它允許你在不修改原函數代碼的前提下,為其添加額外功能。這在實際開發中特別有用,比如權限校驗、日志記錄、性能統計等場景。
什么是裝飾器(Decorator)
裝飾器本質上是一個函數,也可以是類,它的作用是在不改變原函數調用方式的情況下,對函數的功能進行擴展。Python 中使用 @ 符號來應用裝飾器,放在函數定義的上方。
例如:
@my_decorator def say_hello(): print("Hello")
上面這段代碼等價于:
立即學習“Python免費學習筆記(深入)”;
def say_hello(): print("Hello") say_hello = my_decorator(say_hello)
也就是說,裝飾器就是把一個函數傳給另一個函數,并返回一個新的函數替代原來的函數。
裝飾器的常見用途
1. 記錄日志 / 函數執行時間
這是裝飾器最典型的應用之一。你可以為多個函數統一加上日志輸出或者計時功能,而無需重復寫代碼。
import time def log_time(func): def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) print(f"Call {func.__name__}, cost {time.time() - start:.4f}s") return result return wrapper @log_time def do_something(): time.sleep(0.5) do_something() # 輸出類似:Call do_something, cost 0.5001s
注意:這里用了 *args 和 **kwargs 來兼容各種參數形式的函數,保證裝飾器的通用性。
2. 權限控制與條件判斷
你可以在執行某個函數前做一些檢查,比如用戶是否登錄、輸入是否合法等。
def login_required(func): def wrapper(user, *args, **kwargs): if user.is_authenticated: return func(user, *args, **kwargs) else: print("請先登錄") return wrapper class User: def __init__(self, is_authenticated): self.is_authenticated = is_authenticated @login_required def Access_data(user): print("訪問數據成功") user = User(is_authenticated=False) access_data(user) # 輸出:請先登錄
這樣的結構可以讓你集中處理權限邏輯,避免在每個業務函數里都加判斷語句。
3. 多層裝飾器疊加使用
你還可以在一個函數上疊加多個裝飾器,它們會按順序從下往上依次執行。
def decorator1(func): def wrapper(*args, **kwargs): print("Start decorator1") result = func(*args, **kwargs) print("End decorator1") return result return wrapper def decorator2(func): def wrapper(*args, **kwargs): print("Start decorator2") result = func(*args, **kwargs) print("End decorator2") return result return wrapper @decorator1 @decorator2 def test(): print("Test function") test() # 輸出: # Start decorator1 # Start decorator2 # Test function # End decorator2 # End decorator1
小技巧:多個裝飾器的執行順序是從內到外,也就是最靠近函數的那個最先被調用。
使用類作為裝飾器
除了函數,類也可以作為裝飾器,只需要實現 __call__ 方法即可。
class MyDecorator: def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): print("Before function call") result = self.func(*args, **kwargs) print("After function call") return result @MyDecorator def say_hi(): print("Hi") say_hi() # 輸出: # Before function call # Hi # After function call
這種方式適合需要維護狀態的情況,比如緩存中間結果、計數器等。
基本上就這些了。裝飾器看起來有點“魔法”,但只要理解它是如何包裝和替換函數的,其實并不難掌握。關鍵是要多練習幾種不同類型的用法,比如帶參數的裝飾器、類方法裝飾器等,才能在實際項目中靈活運用。