使用类装饰器捕获构造函数参数且不破坏继承
类装饰器破坏继承关系,实例化子类时报错
错误信息
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
相关产品推荐
相关产品推荐

