當前位置: 首頁>>AGI專欄>>正文


Python裝飾模式用法及代碼示例

以下是 Python 裝飾器模式 的詳細用法解析與實用示例,涵蓋函數裝飾器、類裝飾器及多層嵌套場景,幫助靈活擴展對象功能:

一、裝飾模式的核心思想

  • 定義:動態地為對象添加額外職責,且不改變其原有結構。
  • 優勢:避免繼承導致的類爆炸,支持運行時功能組合。
  • Python特性:通過 @ 語法糖簡化實現,本質是 高階函數 或 類包裝

二、函數裝飾器實現

1. 基礎裝飾器(無參)

def logger(func):
    def wrapper(*args, **kwargs):
        print(f"開始執行: {func.__name__}")
        result = func(*args, **kwargs)
        print(f"執行結束: {func.__name__}")
        return result
    return wrapper

@logger
def add(a, b):
    return a + b

print(add(2, 3))  
# 輸出:
# 開始執行: add
# 執行結束: add
# 5

2. 帶參數的裝飾器

def repeat(times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(3)
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")
# 輸出:
# Hello, Alice!
# Hello, Alice!
# Hello, Alice!

三、類裝飾器實現

1. 裝飾器類(基於 __call__ 方法)

class Timer:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        import time
        start = time.time()
        result = self.func(*args, **kwargs)
        end = time.time()
        print(f"{self.func.__name__} 耗時: {end - start:.2f}秒")
        return result

@Timer
def heavy_computation(n):
    return sum(i*i for i in range(n))

heavy_computation(10**6)  # 輸出: heavy_computation 耗時: 0.12秒

2. 裝飾器類(帶參數)

class PermissionCheck:
    def __init__(self, role):
        self.role = role

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            if self.role == "admin":
                return func(*args, **kwargs)
            else:
                raise PermissionError("權限不足")
        return wrapper

@PermissionCheck(role="admin")
def delete_file(filename):
    print(f"刪除文件: {filename}")

delete_file("test.txt")  # 輸出: 刪除文件: test.txt

@PermissionCheck(role="user")
def read_file(filename):
    print(f"讀取文件: {filename}")

read_file("test.txt")  # 拋出 PermissionError

四、多層裝飾器執行順序

裝飾器按 從下到上 的順序應用:

@decorator1
@decorator2
def my_func():
    pass

# 等價於:
my_func = decorator1(decorator2(my_func))

示例

def bold(func):
    def wrapper():
        return "<b>" + func() + "</b>"
    return wrapper

def italic(func):
    def wrapper():
        return "<i>" + func() + "</i>"
    return wrapper

@bold
@italic
def say_hello():
    return "Hello"

print(say_hello())  # 輸出: <b><i>Hello</i></b>

五、裝飾器的典型應用場景

  1. 日誌記錄與性能監控
    跟蹤函數執行時間和參數。
  2. 權限驗證
    限製接口訪問權限(如用戶角色檢查)。
  3. 緩存與記憶化
    存儲函數結果避免重複計算:

    from functools import lru_cache
    
    @lru_cache(maxsize=128)
    def fibonacci(n):
        if n < 2:
            return n
        return fibonacci(n-1) + fibonacci(n-2)
  4. 路由注冊(Web框架)
    Flask 框架的路由裝飾器:

    @app.route("/")
    def home():
        return "Welcome"
  5. 輸入驗證與格式化
    確保函數參數符合預期:

    python
    Copy
    def validate_int_args(func):
        def wrapper(*args):
            if all(isinstance(arg, int) for arg in args):
                return func(*args)
            else:
                raise ValueError("參數必須為整數")
        return wrapper

六、注意事項與調試技巧

  1. 保留元信息
    使用 functools.wraps 保持原函數屬性(如 __name__):

    from functools import wraps
    
    def debug(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            print(f"調用 {func.__name__}")
            return func(*args, **kwargs)
        return wrapper
  2. 處理帶狀態的裝飾器
    類裝飾器適合需保存狀態的場景(如計數器):

    class Counter:
        def __init__(self, func):
            self.func = func
            self.count = 0
    
        def __call__(self, *args, **kwargs):
            self.count += 1
            print(f"執行次數: {self.count}")
            return self.func(*args, **kwargs)
    
    @Counter
    def example():
        pass
  3. 避免循環裝飾
    多層裝飾可能引發意外行為,需謹慎設計執行順序。

總結

Python 裝飾器模式通過 高階函數 或 類包裝 實現功能擴展,結合 @ 語法糖可顯著提升代碼可讀性。合理使用裝飾器能實現以下目標:

  • 代碼複用:抽離通用邏輯(如日誌、權限)。
  • 關注點分離:業務代碼與輔助功能解耦。
  • 動態擴展:運行時靈活組合功能模塊。

掌握裝飾器模式是編寫優雅 Python 代碼的關鍵技能!

本文由《純淨天空》出品。文章地址: https://vimsky.com/zh-tw/article/4851.html,轉載請注明來源鏈接。