Administrator
Published on 2025-03-14 / 7 Visits
0
0

Python 装饰器原理与应用详解

装饰器是 Python 中用于动态增强函数或类功能的工具,其核心思想是在不修改原有代码的前提下增加新功能。以下是装饰器的详细解析:


一、装饰器工作原理

核心机制:装饰器本质是一个可调用对象(函数或类),通过闭包和函数替换实现功能扩展。

def decorator(func):
    def wrapper(*args, **kwargs):
        print("Before execution")
        result = func(*args, **kwargs)  # 调用原函数
        print("After execution")
        return result
    return wrapper

@decorator
def target_function():
    print("Target function executed")

# 调用 target_function() 实际执行的是 wrapper()

二、函数装饰器 vs 类装饰器

特性函数装饰器类装饰器
实现方式通过嵌套函数和闭包通过类的 __call__ 方法实现实例可调用
状态管理使用闭包变量或 nonlocal 关键字使用实例属性
可扩展性适合简单逻辑适合需要维护复杂状态的场景
装饰目标主要装饰函数,也可装饰类可装饰函数或类
典型应用场景日志、计时、权限校验需要多次初始化的装饰逻辑

类装饰器示例

class ClassDecorator:
    def __init__(self, func):
        self.func = func
        self.call_count = 0  # 维护状态

    def __call__(self, *args, **kwargs):
        self.call_count += 1
        print(f"Call count: {self.call_count}")
        return self.func(*args, **kwargs)

@ClassDecorator
def my_func():
    print("Function executed")

三、自定义复杂装饰器技巧

1. 带参数的装饰器

需三层嵌套结构:

def param_decorator(level="INFO"):
    def actual_decorator(func):
        def wrapper(*args, **kwargs):
            print(f"[{level}] Entering {func.__name__}")
            return func(*args, **kwargs)
        return wrapper
    return actual_decorator

@param_decorator(level="DEBUG")
def debug_function():
    pass

2. 装饰器堆叠

执行顺序从下往上:

@decorator1
@decorator2
def func():
    pass
# 等价于 decorator1(decorator2(func))()

3. 保留元数据

使用 functools.wraps 保持原函数信息:

from functools import wraps

def meta_preserving_decorator(func):
    @wraps(func)  # 关键语句
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

四、高级应用场景

1. 性能统计装饰器

import time

def timer(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        duration = time.perf_counter() - start
        print(f"{func.__name__} took {duration:.4f} seconds")
        return result
    return wrapper

2. 访问控制装饰器

def admin_required(func):
    @wraps(func)
    def wrapper(user, *args, **kwargs):
        if not user.is_admin:
            raise PermissionError("Admin access required")
        return func(user, *args, **kwargs)
    return wrapper

@admin_required
def delete_database(user):
    print("Database deleted!")

3. 类方法装饰器

def class_decorator(cls):
    cls.new_method = lambda self: print("Added method")
    return cls

@class_decorator
class MyClass:
    pass

obj = MyClass()
obj.new_method()  # 输出 "Added method"

五、关键注意事项

  1. 装饰器执行时机:在模块导入时立即执行装饰逻辑,而非函数调用时
  2. 装饰器顺序:离函数近的装饰器先执行(由内到外)
  3. 异常处理:装饰器中需合理处理异常传播

通过灵活组合这些技术,可以创建出适应各种场景的强大装饰器,实现代码的优雅复用和功能扩展。


Comment