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

使用类装饰器捕获构造函数参数且不破坏继承

类装饰器破坏继承关系,实例化子类时报错

错误信息

ERROR!
Traceback (most recent call last):
  File "<string>", line 22, in <module>
TypeError: MyDecorator.__init__() takes 2 positional arguments but 4 were given

问题原因

用类装饰器@MyDecorator装饰BaseClass后,BaseClass不再是原本的类,而是MyDecorator的实例。当SubClass尝试继承这个实例时,Python在创建子类的过程中会调用父类(即MyDecorator实例)的构造方法,但MyDecorator.__init__只接受2个参数,而创建子类时会自动传递4个参数(类名、基类元组、命名空间等),因此触发参数不匹配的错误。

解决方案

要保留继承关系同时捕获构造参数,最简单的方式是将装饰器改为返回继承原类的子类,而非返回装饰器类的实例。这样BaseClass仍然是一个类,子类继承时不会破坏原有继承链。

修改后的代码

def MyDecorator(original_class):
    # 创建继承原类的包装类
    class WrappedClass(original_class):
        def __init__(self, *args, **kwargs):
            # 捕获并打印构造参数
            print(f"Decorator: Creating instance with arguments: {args}, {kwargs}")
            # 调用原类构造方法
            super().__init__(*args, **kwargs)
    return WrappedClass

@MyDecorator
class BaseClass:
    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2

class SubClass(BaseClass):
    def additional_method(self):
        print("Additional method in SubClass")

# 测试基类实例化
base_instance = BaseClass("foo", arg2="bar")
print(f"arg1: {base_instance.arg1}, arg2: {base_instance.arg2}")

# 测试子类实例化
sub_instance = SubClass("baz", arg2="qux")
print(f"arg1: {sub_instance.arg1}, arg2: {sub_instance.arg2}")

# 调用子类专属方法
sub_instance.additional_method()

代码说明

  • 装饰器MyDecorator接收原类后,返回一个继承自原类的WrappedClass
  • WrappedClass重写__init__方法,先捕获并打印构造参数,再通过super()调用原类的构造逻辑
  • 此时BaseClass仍为类类型,SubClass继承它完全符合Python继承规则,不会触发错误
  • 基类和子类的实例化参数都会被装饰器捕获并打印

类装饰器替代实现(基于元类)

如果一定要用类装饰器形式,可以让装饰器类继承type(元类),确保返回的实例本身是类:

class MyDecorator(type):
    def __new__(cls, name, bases, attrs):
        original_class = super().__new__(cls, name, bases, attrs)
        class WrappedClass(original_class):
            def __init__(self, *args, **kwargs):
                print(f"Decorator: Creating instance with arguments: {args}, {kwargs}")
                super().__init__(*args, **kwargs)
        return WrappedClass

@MyDecorator
class BaseClass:
    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2

# 子类定义与测试逻辑和之前一致

这种方式通过元类创建新类,同样能保证继承关系正常,但写法比函数装饰器复杂,推荐优先使用第一种方案。

内容的提问来源于stack exchange,提问作者epi.log

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 23:36:03