Python 裝飾器使用:八個裝飾器的巧妙應用
裝飾器是Python中一種強大的工具,它們可以讓你修改或增強函數、方法甚至類的行為,就像是給你的代碼披上一層魔法斗篷。今天,我們將通過10個實用的裝飾器應用,從基礎到進階,一步步揭開它的面紗。
1. 簡單的時間統計裝飾器
目的:計算函數執行時間,了解性能。
import time
def timing_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} took {end_time - start_time:.4f} seconds")
return result
return wrapper
@timing_decorator
def example_function(n):
sum(range(n))
example_function(1000000)
解釋:這個裝飾器記錄了被裝飾函數的開始和結束時間,然后計算并打印出耗時。它使用了*args 和 **kwargs 來保持函數的通用性。
2. 參數驗證裝飾器
用途:確保函數輸入參數滿足特定條件。
def positive_number_decorator(func):
def wrapper(number):
if number < 0:
raise ValueError("Number must be positive.")
return func(number)
return wrapper
@positive_number_decorator
def square(number):
return number ** 2
try:
print(square(-5))
except ValueError as e:
print(e)
技巧:通過拋出異常來處理不滿足條件的情況,保持函數接口的清晰。
3. 緩存裝飾器
目的:提高效率,避免重復計算。
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n <= 1:
return n
else:
return (fibonacci(n-1) + fibonacci(n-2))
print(fibonacci(30)) # 只計算一次
注意:lru_cache是一個內置的緩存實現,非常適合用于耗時的計算任務。
4. 日志記錄裝飾器
用途:自動記錄函數調用信息。
def log_decorator(func):
def wrapper(*args, **kwargs):
print(f"Calling function: {func.__name__}")
result = func(*args, **kwargs)
print(f"Function {func.__name__} returned: {result}")
return result
return wrapper
@log_decorator
def add(a, b):
return a + b
add(5, 3)
技巧:這有助于調試和監控程序運行。
5. 類方法裝飾器
場景:在類方法上添加額外邏輯。
def class_method_logger(cls_method):
def wrapper(self, *args, **kwargs):
print(f"Calling method '{cls_method.__name__}' on {self.__class__.__name__}")
return cls_method(self, *args, **kwargs)
return wrapper
class MyClass:
@class_method_logger
def say_hello(self, name):
print(f"Hello, {name}")
MyClass().say_hello("World")
理解:裝飾器同樣適用于類方法,增加類行為的靈活性。
6. 異常處理裝飾器
目的:統一異常處理邏輯。
def handle_exceptions(func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
print(f"Error in {func.__name__}: {e}")
return wrapper
@handle_exceptions
def divide(a, b):
return a / b
divide(10, 0) # 安全地處理除零錯誤
7. 計數裝飾器
應用場景:跟蹤函數調用次數。
class Counter:
def __init__(self, func):
self.func = func
self.calls = 0
def __call__(self, *args, **kwargs):
self.calls += 1
print(f"Call {self.calls} of {self.func.__name__}")
return self.func(*args, **kwargs)
@Counter
def greet():
print("Hello!")
greet()
greet()
8. 參數默認值檢查裝飾器
使用:確保函數參數符合預期值。
def check_parameters(expected):
def decorator(func):
def wrapper(*args, **kwargs):
for key, value in kwargs.items():
if key in expected and value != expected[key]:
raise ValueError(f"Invalid value for {key}. Expected {expected[key]}, got {value}.")
return func(*args, **kwargs)
return wrapper
return decorator
@check_parameters({"difficulty": "easy"})
def start_game(difficulty):
print(f"Starting game with difficulty level {difficulty}.")
start_game(difficulty="medium") # 觸發異常
實戰案例:Web請求計時與日志記錄
假設我們有一個簡單的Web請求函數,我們想要記錄每次請求的時間并簡單記錄日志。
import requests
from datetime import datetime
def request_logger(url):
def decorator(func):
def wrapper(*args, **kwargs):
start = datetime.now()
response = func(url, *args, **kwargs)
end = datetime.now()
print(f"Request to {url} completed in {end - start}. Status Code: {response.status_code}")
return response
return wrapper
return decorator
@request_logger("https://api.example.com/data")
def make_request(url):
return requests.get(url)
make_request()
分析:這個案例展示了如何結合使用多個功能(計時和日志記錄)于一個裝飾器中,以監控API調用。在實際開發中,這樣的裝飾器可以極大地幫助監控和優化服務性能。
通過上述示例,我們不僅掌握了裝飾器的基礎和進階應用,還學會了如何根據實際需求設計和實現裝飾器,以增強代碼的功能性和可維護性。