Python类装饰器应用_元编程解析【教程】

类装饰器是实现了__call__方法的类,用于修饰其他类或函数,支持状态保存和参数配置,比函数装饰器更灵活;典型应用包括调用监控、类注册和接口约束。

类装饰器是 Python 元编程中非常实用的工具,它让类本身具备“修饰其他类或函数”的能力,比函数装饰器更灵活,也更适合封装状态和复用逻辑。

什么是类装饰器

类装饰器是一个实现了 __call__ 方法的类。当它被用作装饰器(即写在 @ 后面)时,Python 会实例化该类,并在被装饰对象定义完成后,自动调用其实例的 __call__ 方法,传入被装饰的目标(函数或类)。

关键点:

  • 必须定义 __init__ 接收被装饰对象(如 func 或 cls)
  • 必须定义 __call__ 来执行实际的增强逻辑
  • 返回值通常是包装后的新可调用对象(如闭包、新函数或代理类)

类装饰器 vs 函数装饰器

函数装饰器简洁,适合无状态的通用逻辑(如日志、计时);类装饰器天然支持保存配置和内部状态,适合需要初始化参数或跨调用维护数据的场景。

例如:统计某个方法被调用了多少次,每次调用都记录时间戳——这类需求用类装饰器更自然:

  • 实例属性可存调用次数、历史列表等状态
  • __init__ 可接收配置参数(如是否启用调试、阈值限制)
  • __call__ 决定如何包装原行为(前置/后置处理、条件跳过、异常捕获等)

典型应用场景

1. 方法调用监控与增强
给类方法添加统一的输入校验、性能打点、权限检查。例如:@TimeIt 记录耗时,@Retry(max_times=3) 自动重试失败调用。

2. 类注册与元信息注入
在类定义时自动将其注册到全局工厂或插件池中,同时注入版本、作者、描述等元数据。

3. 接口契约约束
强制被装饰类实现特定方法、满足协议(Protocol),或对 __init__ 参数做运行时校验。

一个可复用的类装饰器示例

下面是一个带参数的类装饰器,用于限制方法调用频率(简单令牌桶):

class RateLimit:
    def __init__(self, max_calls=5, window=60):
        self.max_calls = max_calls
        self.window = window
        self.calls = []
def __call__(self, func):
    def wrapper(*args, **kwargs):
        now = time.time()
        # 清理过期记录
        self.calls = [t for t in self.calls if now - t < self.window]
        if len(self.calls) >= self.max_calls:
            raise RuntimeError("Rate limit exceeded")
        self.calls.append(now)
        return func(*args, **kwargs)
    return wrapper

使用方式:
@RateLimit(max_calls=3, window=10)
def api_call(): ...

注意:这个例子中 calls 状态是共享的——因为所有被同一 RateLimit 实例装饰的方法共用一个 self.calls。如需每个方法独立限流,应在 wrapper 内部维护状态,或改用装饰器工厂模式。