You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多装饰器场景下Mixin类继承装饰器失效问题求助

解决子类继承父类多装饰器丢失的问题

原实现的核心问题有两个:

  1. 装饰器仅绑定了自身,多个装饰器叠加时,只有最外层的装饰器能被Mixin检测到,内层装饰器的信息被包裹在函数内部无法获取
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 23:36:21