想像你是個繁忙廚房裡的廚師。如果你願意的話,你有一個食譜——一個函數。隨著時間的推移,您會發現大多數菜餚在上桌前都需要淋上一點橄欖油、少許鹽或撒上香草。與其手動為每道菜添加這些最後的修飾,有一個自動應用它們的助手不是很方便嗎?這正是 Python 裝飾器可以為您的程式碼做的事情——以優雅、可重複使用且富有表現力的方式添加功能。
在本文中,我們將探索高階 Python 裝飾器的世界。我們將超越基礎知識,深入研究參數化裝飾器、可堆疊裝飾器,甚至帶有類別的裝飾器。我們還將重點介紹最佳實踐和要避免的陷阱。準備好?開始做飯吧!
在深入探討之前,讓我們先回顧一下基礎知識。 Python 中的裝飾器只是一個函數,它接受另一個函數(或方法)作為參數,對其進行擴充,然後傳回一個新函數。這是一個例子:
# Basic decorator example def simple_decorator(func): def wrapper(*args, **kwargs): print(f"Calling {func.__name__}...") result = func(*args, **kwargs) print(f"{func.__name__} finished.") return result return wrapper @simple_decorator def say_hello(): print("Hello, world!") say_hello()
輸出:
Calling say_hello... Hello, world! say_hello finished.
現在,讓我們進入高階用例。
有時,裝飾器需要接受自己的參數。例如,如果我們想要一個裝飾器來記錄不同程度的訊息(資訊、偵錯、錯誤)怎麼辦?
# Parameterized decorator example def log(level): def decorator(func): def wrapper(*args, **kwargs): print(f"[{level}] Calling {func.__name__}...") result = func(*args, **kwargs) print(f"[{level}] {func.__name__} finished.") return result return wrapper return decorator @log("INFO") def process_data(): print("Processing data...") process_data()
輸出:
[INFO] Calling process_data... Processing data... [INFO] process_data finished.
這種分層結構(傳回裝飾器的函數)是創建靈活的參數化裝飾器的關鍵。
Python 允許將多個裝飾器應用於單一函數。讓我們建立兩個裝飾器並將它們堆疊起來。
# Stackable decorators def uppercase(func): def wrapper(*args, **kwargs): result = func(*args, **kwargs) return result.upper() return wrapper def exclaim(func): def wrapper(*args, **kwargs): result = func(*args, **kwargs) return result + "!!!" return wrapper @uppercase @exclaim def greet(): return "hello" print(greet())
輸出:
HELLO!!!
這裡,裝飾器以自下而上的方式應用:@exclaim 包裝問候,@uppercase 包裝結果。
Python 的一個鮮為人知的功能是類別可以用作裝飾器。當您需要維護狀態時,這特別有用。
# Class-based decorator class CountCalls: def __init__(self, func): self.func = func self.call_count = 0 def __call__(self, *args, **kwargs): self.call_count += 1 print(f"Call {self.call_count} to {self.func.__name__}") return self.func(*args, **kwargs) @CountCalls def say_hello(): print("Hello!") say_hello() say_hello()
輸出:
Call 1 to say_hello Hello! Call 2 to say_hello Hello!
這裡,call 方法使類別能夠像函數一樣運行,從而允許它無縫地包裝目標函數。
裝飾器與類別中的方法一樣有效。然而,正確處理自我是至關重要的。
# Method decorator example def log_method(func): def wrapper(self, *args, **kwargs): print(f"Method {func.__name__} called on {self}") return func(self, *args, **kwargs) return wrapper class Greeter: @log_method def greet(self, name): print(f"Hello, {name}!") obj = Greeter() obj.greet("Alice")
輸出:
Method greet called on <__main__.Greeter object at 0x...> Hello, Alice!
有時,您需要將裝飾器與資源管理整合。例如,讓我們建立一個裝飾器來對函數的執行進行計時。
import time # Timing decorator def time_it(func): def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) end = time.time() print(f"{func.__name__} took {end - start:.2f} seconds") return result return wrapper @time_it def slow_function(): time.sleep(2) print("Done sleeping!") slow_function()
輸出:
# Basic decorator example def simple_decorator(func): def wrapper(*args, **kwargs): print(f"Calling {func.__name__}...") result = func(*args, **kwargs) print(f"{func.__name__} finished.") return result return wrapper @simple_decorator def say_hello(): print("Hello, world!") say_hello()
與裝飾器合作時,保持可讀性和可維護性至關重要。這裡有一些提示:
Calling say_hello... Hello, world! say_hello finished.
徹底測試:裝飾器可能會引入微妙的錯誤,尤其是在連結多個裝飾器時。
文件裝飾器:清楚記錄每個裝飾器的作用及其預期參數。
避免過度使用:雖然裝飾器很強大,但過度使用它們會使程式碼難以理解。
裝飾器是 Python 最具表現力的功能之一。它們允許您以乾淨、可重複使用的方式擴展和修改行為。從參數化裝飾器到基於類別的實現,可能性是無限的。當你磨練你的技能時,你會發現自己利用裝飾器來編寫更乾淨、更Pythonic的程式碼——也許,就像一位偉大的廚師一樣,在你製作的每一個食譜中創造出你的標誌性風格。
註:AI輔助內容
以上是進階 Python 裝飾器:提升您的程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!