类装饰器是用类实现的装饰器,通过__call__方法使实例可调用,天然支持状态保持与参数扩展;带参形式需外层接收参数、内层封装逻辑;虽非元编程本身,但常作为其轻量入口,可协同__set_name__、元类等实现动态行为修改。

什么是类装饰器
类装饰器是用类来实现的装饰器,它通过实现 __call__ 方法,让实例可以像函数一样被调用。与函数装饰器不同,类装饰器天然支持状态保持(比如计数、缓存、配置),也更容易扩展初始化参数和生命周期逻辑。
基础写法:一个可调用的类
要让类能当装饰器用,关键在于定义 __call__ 方法,并在初始化时接收被装饰对象(函数或方法):
- 在 __init__ 中保存被装饰的目标(如函数)
- 在 __call__ 中实现实际增强逻辑(如前置/后置操作、包装调用)
- 返回结果通常要调用原函数,也可拦截或改写行为
示例:
class LogCall:
def __init__(self, func):
self.func = func
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"[Log] Calling {self.func.__name__} (#{self.count})")
return self.func(*args, **kwargs)@LogCall
def say_hello(name):
return f"Hello, {name}!"
带参数的类装饰器
若想支持 @LogCall(level="DEBUG") 这种带参形式,需多嵌套一层:外层类接收装饰器参数,内层类接收被装饰对象。本质是「返回装饰器类的实例」而非直接实例化。
立即学习“Python免费学习笔记(深入)”;
- 外层 __init__ 接收装饰器参数(如 level、verbose)
- 外层 __call__ 返回真正的装饰器类实例(即接收 func 的那一层)
- 内层类负责保存 func 并定义实际调用逻辑
示例:
class LogCall:
def __init__(self, level="INFO"):
self.level = level
def __call__(self, func):
# 返回一个真正执行装饰的类实例
class Wrapper:
def __init__(self, f):
self.func = f
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"[{self.level}] {self.func.__name__} called {self.count} time(s)")
return self.func(*args, **kwargs)
return Wrapper(func)@LogCall(level="DEBUG")
def add(a, b):
return a + b
类装饰器与元编程的关系
类装饰器本身不是元编程,但它常作为元编程的轻量入口——因为它在类/函数定义后、使用前介入,能动态修改行为。真正体现元编程的是配合 __set_name__、描述符、__getattribute__ 或 type() 动态创建类 等机制。
- 可结合 __set_name__ 实现属性级装饰(如验证字段)
- 可在 __call__ 中动态生成方法、注入属性,甚至重写 __dict__
- 与 metaclass 协同时,能在类创建阶段统一应用装饰逻辑
例如,用类装饰器自动为方法添加性能计时,再通过元类批量注册到监控中心——这就是典型的元编程组合用法。











