Python中十個常用的自定義裝飾器的使用詳解
裝飾器是 Python 中一項強大而靈活的功能,它允許我們在不修改原始代碼的情況下,為函數(shù)或類添加額外的功能。無論是性能優(yōu)化、調(diào)試輔助還是代碼健壯性提升,裝飾器都能讓我們的開發(fā)工作事半功倍。
下面分享 10 個簡單但超級有用的自定義裝飾器,每一個都配有完整的代碼實現(xiàn)和使用示例。
1. @timer - 測量函數(shù)執(zhí)行時間
優(yōu)化代碼性能時,了解函數(shù)的執(zhí)行時間至關(guān)重要。@timer 裝飾器可以輕松跟蹤函數(shù)的運行時長:
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} 執(zhí)行耗時: {end_time - start_time:.2f} 秒")
return result
return wrapper
@timer
def process_large_dataset():
"""模擬處理大型數(shù)據(jù)集"""
data = [x ** 2 for x in range(1000000)]
return sum(data)
# 使用示例
result = process_large_dataset()
print(f"處理結(jié)果: {result}")
2. @memoize - 緩存函數(shù)結(jié)果
對于計算成本高的函數(shù),@memoize 可以緩存結(jié)果,避免相同輸入的重復計算:
def memoize(func):
cache = {}
def wrapper(*args):
if args in cache:
print(f"從緩存中獲取結(jié)果: {args} -> {cache[args]}")
return cache[args]
result = func(*args)
cache[args] = result
print(f"計算并緩存結(jié)果: {args} -> {result}")
return result
return wrapper
@memoize
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
# 使用示例
print(fibonacci(10)) # 第一次計算
print(fibonacci(10)) # 從緩存獲取
3. @validate_input - 參數(shù)驗證
確保函數(shù)接收到的參數(shù)符合預期標準:
def validate_input(*expected_types):
def decorator(func):
def wrapper(*args, **kwargs):
for i, (arg, expected_type) in enumerate(zip(args, expected_types)):
if not isinstance(arg, expected_type):
raise TypeError(f"參數(shù) {i} 應(yīng)該是 {expected_type} 類型,但得到的是 {type(arg)}")
return func(*args, **kwargs)
return wrapper
return decorator
@validate_input(list, int)
def get_list_slice(data, n):
"""獲取列表的前n個元素"""
return data[:n]
# 使用示例
try:
result = get_list_slice([1, 2, 3, 4, 5], 3)
print(f"切片結(jié)果: {result}")
get_list_slice("不是列表", 3) # 這會拋出異常
except TypeError as e:
print(f"錯誤: {e}")
4. @log_results - 記錄函數(shù)輸出
在復雜的數(shù)據(jù)分析任務(wù)中,記錄函數(shù)結(jié)果對于調(diào)試和監(jiān)控非常有幫助:
def log_results(log_file="function_results.log"):
def decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
with open(log_file, "a", encoding="utf-8") as f:
f.write(f"{func.__name__} - 參數(shù): {args} {kwargs} - 結(jié)果: {result}\n")
return result
return wrapper
return decorator
@log_results("calculations.log")
def calculate_statistics(numbers):
"""計算數(shù)據(jù)的統(tǒng)計信息"""
if not numbers:
return None
return {
'sum': sum(numbers),
'mean': sum(numbers) / len(numbers),
'max': max(numbers),
'min': min(numbers)
}
# 使用示例
stats = calculate_statistics([10, 20, 30, 40, 50])
print(f"統(tǒng)計結(jié)果: {stats}")
5. @suppress_errors - 優(yōu)雅的錯誤處理
防止意外錯誤中斷整個執(zhí)行流程:
def suppress_errors(default_return=None):
def decorator(func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
print(f"函數(shù) {func.__name__} 執(zhí)行出錯: {e}")
return default_return
return wrapper
return decorator
@suppress_errors(default_return=0)
def safe_divide(a, b):
"""安全的除法運算"""
return a / b
# 使用示例
print(f"10 / 2 = {safe_divide(10, 2)}")
print(f"10 / 0 = {safe_divide(10, 0)}") # 不會崩潰,返回默認值0
6. @validate_output - 輸出驗證
確保函數(shù)輸出符合質(zhì)量標準:
def validate_output(validation_func):
def decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
if validation_func(result):
return result
else:
raise ValueError(f"函數(shù) {func.__name__} 的輸出未通過驗證: {result}")
return wrapper
return decorator
def is_positive_number(x):
"""驗證是否為正數(shù)"""
return isinstance(x, (int, float)) and x > 0
@validate_output(is_positive_number)
def process_value(x):
"""處理數(shù)值,確保返回正數(shù)"""
return abs(x) + 1
# 使用示例
try:
print(f"處理 -5: {process_value(-5)}")
print(f"處理 10: {process_value(10)}")
except ValueError as e:
print(f"驗證失敗: {e}")
7. @retry - 自動重試機制
在網(wǎng)絡(luò)請求等可能臨時失敗的操作中自動重試:
import time
import random
def retry(max_attempts=3, delay=1, backoff=2):
def decorator(func):
def wrapper(*args, **kwargs):
attempts = 0
current_delay = delay
while attempts < max_attempts:
try:
return func(*args, **kwargs)
except Exception as e:
attempts += 1
if attempts == max_attempts:
raise Exception(f"超過最大重試次數(shù) ({max_attempts}),最后錯誤: {e}")
print(f"第 {attempts} 次嘗試失敗,{current_delay} 秒后重試... 錯誤: {e}")
time.sleep(current_delay)
current_delay *= backoff # 指數(shù)退避
return wrapper
return decorator
@retry(max_attempts=3, delay=1)
def unreliable_operation():
"""模擬可能失敗的操作"""
if random.random() < 0.7: # 70% 的失敗率
raise Exception("隨機失敗!")
return "操作成功!"
# 使用示例
try:
result = unreliable_operation()
print(result)
except Exception as e:
print(f"最終失敗: {e}")
8. @debug - 調(diào)試助手
自動打印函數(shù)的輸入?yún)?shù)和返回值,簡化調(diào)試過程:
def debug(verbose=True):
def decorator(func):
def wrapper(*args, **kwargs):
if verbose:
print(f"?? 調(diào)用 {func.__name__}")
print(f" 參數(shù): {args}")
print(f" 關(guān)鍵字參數(shù): {kwargs}")
result = func(*args, **kwargs)
if verbose:
print(f" 返回值: {result}")
print(f"? {func.__name__} 執(zhí)行完成\n")
return result
return wrapper
return decorator
@debug(verbose=True)
def complex_calculation(a, b, coefficient=1.5):
"""執(zhí)行復雜計算"""
intermediate = (a ** 2 + b ** 2) ** 0.5
return intermediate * coefficient
# 使用示例
result = complex_calculation(3, 4, coefficient=2)
9. @deprecated - 標記過時函數(shù)
當函數(shù)不再推薦使用時,向用戶發(fā)出警告:
import warnings
def deprecated(replacement=None):
def decorator(func):
def wrapper(*args, **kwargs):
message = f"函數(shù) '{func.__name__}' 已過時,將在未來版本中移除。"
if replacement:
message += f" 請使用 '{replacement}' 代替。"
warnings.warn(message, DeprecationWarning, stacklevel=2)
return func(*args, **kwargs)
return wrapper
return decorator
@deprecated(replacement="new_data_processor")
def old_data_processor(data):
"""舊的數(shù)據(jù)處理函數(shù)"""
return [x * 2 for x in data]
def new_data_processor(data):
"""新的數(shù)據(jù)處理函數(shù)"""
return [x ** 2 for x in data]
# 使用示例
data = [1, 2, 3, 4, 5]
result = old_data_processor(data) # 會顯示過時警告
print(f"舊方法結(jié)果: {result}")
10. @visualize_results - 自動可視化
為數(shù)據(jù)分析函數(shù)自動生成可視化結(jié)果:
import matplotlib.pyplot as plt
def visualize_results(title=None):
def decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
# 創(chuàng)建可視化
plt.figure(figsize=(10, 6))
if isinstance(result, (list, tuple)):
plt.plot(result, marker='o', linestyle='-', color='blue')
plt.xlabel('索引')
plt.ylabel('值')
elif isinstance(result, dict):
keys = list(result.keys())
values = list(result.values())
plt.bar(keys, values, color='skyblue')
plt.xlabel('鍵')
plt.ylabel('值')
plot_title = title or f"{func.__name__} 結(jié)果可視化"
plt.title(plot_title)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
return result
return wrapper
return decorator
@visualize_results("月度銷售數(shù)據(jù)趨勢")
def analyze_sales_trend():
"""模擬分析銷售趨勢"""
# 模擬月度銷售數(shù)據(jù)
months = ['1月', '2月', '3月', '4月', '5月', '6月']
sales = [120, 150, 130, 170, 200, 180]
return dict(zip(months, sales))
# 使用示例
sales_data = analyze_sales_trend()
print(f"銷售數(shù)據(jù): {sales_data}")
總結(jié)
這些裝飾器展示了 Python 裝飾器的強大威力。通過簡單的 @ 語法,我們就能為函數(shù)添加緩存、日志、驗證、重試等復雜功能,而無需修改原始函數(shù)代碼。
在實際項目中,你可以根據(jù)具體需求組合使用這些裝飾器,或者創(chuàng)建自己的定制裝飾器。掌握裝飾器不僅能讓你的代碼更加簡潔優(yōu)雅,還能顯著提升開發(fā)效率和代碼質(zhì)量。
使用技巧:
- 多個裝飾器可以堆疊使用,執(zhí)行順序是從下往上
- 使用
functools.wraps可以保留原函數(shù)的元信息 - 裝飾器也可以接受參數(shù),實現(xiàn)更靈活的功能配置
以上就是Python中十個常用的自定義裝飾器的使用詳解的詳細內(nèi)容,更多關(guān)于Python自定義裝飾器的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python爬蟲設(shè)置Cookie解決網(wǎng)站攔截并爬取螞蟻短租的問題
這篇文章主要介紹了Python爬蟲設(shè)置Cookie解決網(wǎng)站攔截并爬取螞蟻短租,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02
Python面向?qū)ο蟪绦蛟O(shè)計示例小結(jié)
這篇文章主要介紹了Python面向?qū)ο蟪绦蛟O(shè)計,結(jié)合實例形式總結(jié)分析了Python面向?qū)ο蟪绦蛟O(shè)計中比較常見的類定義、實例化、繼承、私有變量等相關(guān)使用技巧與操作注意事項,需要的朋友可以參考下2019-01-01
用pushplus+python監(jiān)控亞馬遜到貨動態(tài)推送微信
這篇文章主要介紹了用pushplus+python監(jiān)控亞馬遜到貨動態(tài)推送微信的示例,幫助大家利用python搶購商品,感興趣的朋友可以了解下2021-01-01

