多装饰器场景下Mixin类继承装饰器失效问题求助
解决子类继承父类多装饰器丢失的问题
原实现的核心问题有两个:
- 装饰器仅绑定了自身,多个装饰器叠加时,只有最外层的装饰器能被Mixin检测到,内层装饰器的信息被包裹在函数内部无法获取
- Mixin的注册表每个方法仅存储单个装饰器,无法保存多装饰器的应用顺序
一、修改装饰器定义,保存完整装饰器链
修改装饰器逻辑,让每个被装饰的函数保存所有叠加的装饰器列表,确保多层装饰器的信息不丢失:
def decorator(func): def wrapper(*args, **kwargs): # 原装饰逻辑保持不变 result = func(*args, **kwargs) return result # 构建并保存装饰器链:如果被装饰对象已有链,将当前装饰器前置 if hasattr(func, 'inherit_decorators'): wrapper.inherit_decorators = [decorator] + func.inherit_decorators else: wrapper.inherit_decorators = [decorator] return wrapper
二、修改Mixin类,支持多装饰器继承
更新Mixin的注册表逻辑,改为存储每个方法的装饰器列表,并按正确顺序重新应用到子类方法上:
class InheritDecoratorsMixin: """Mixin Class that allows to inherit multiple decorators in order. Each subclass of this class will have a '_decorator_registry' attribute which contains lists of decorators to be applied for each method. Each decorator output must contain the attribute 'inherit_decorators' with the list of decorators in application order (outer to inner). """ def __init_subclass__(cls, *args, **kwargs): super().__init_subclass__(*args, **kwargs) # 从父类继承注册表,避免修改父类的原始数据 decorator_registry = getattr(cls, '_decorator_registry', {}).copy() cls._decorator_registry = decorator_registry # 注册Mixin自身的带装饰器的方法 for name, obj in __class__.__dict__.items(): if hasattr(obj, 'inherit_decorators') and name not in decorator_registry: decorator_registry[name] = obj.inherit_decorators.copy() # 注册当前子类新定义的带装饰器的方法 for name, obj in cls.__dict__.items(): if hasattr(obj, 'inherit_decorators'): # 子类重写方法时,覆盖注册表中的装饰器链 decorator_registry[name] = obj.inherit_decorators.copy() # 按顺序将装饰器应用到子类方法上 for name, decorators in decorator_registry.items(): if name not in cls.__dict__: continue current_method = cls.__dict__[name] # 检查当前方法是否已经应用了正确的装饰器链 current_decorators = getattr(current_method, 'inherit_decorators', []) if current_decorators != decorators: # 逆序应用装饰器:保证和原父类的装饰顺序一致(内层先应用) decorated_method = current_method for dec in reversed(decorators): decorated_method = dec(decorated_method) setattr(cls, name, decorated_method)
三、测试验证
用示例代码验证效果:
# 定义测试装饰器 def decorator1(func): def wrapper(*args, **kwargs): print("执行 decorator1") return func(*args, **kwargs) if hasattr(func, 'inherit_decorators'): wrapper.inherit_decorators = [decorator1] + func.inherit_decorators else: wrapper.inherit_decorators = [decorator1] return wrapper def decorator2(func): def wrapper(*args, **kwargs): print("执行 decorator2") return func(*args, **kwargs) if hasattr(func, 'inherit_decorators'): wrapper.inherit_decorators = [decorator2] + func.inherit_decorators else: wrapper.inherit_decorators = [decorator2] return wrapper # 父类 class Example(InheritDecoratorsMixin): @decorator1 @decorator2 def method(self): print("执行父类 method") # 子类 class SubExample(Example): def method(self): print("执行子类 method") # 测试调用 sub = SubExample() sub.method()
执行后会输出:
执行 decorator1 执行 decorator2 执行子类 method
说明两个装饰器都被正确继承并按顺序执行。
内容的提问来源于stack exchange,提问作者Patricio
相关产品推荐
相关产品推荐

