多类继承下如何让super().__init__()调用所有父类构造方法?
解决Python多继承中调用所有父类构造函数的问题
原代码中,类C继承自A和B,仅通过super().__init__()只能调用第一个父类A的构造函数,导致B的属性未被初始化。要在不硬编码父类名称的前提下调用所有父类的构造函数,有两种可行方案:
方案1:利用MRO链式调用(推荐)
这种方法要求所有父类的构造函数也通过super()调用,让Python的方法解析顺序(MRO)自动处理链式调用。即使后续新增父类,也无需修改C的代码。
修改后的代码:
import inspect class A: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.atr1 = 'Foo1' class B: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.atr2 = 'Foo2' class C(A,B): def __init__(self) -> None: super().__init__() # 验证代码 fooObj = C() for i in inspect.getmembers(fooObj): if not i[0].startswith('_') and not inspect.ismethod(i[1]): print(i)
输出结果:
('atr1', 'Foo1') ('atr2', 'Foo2')
原理:C的MRO顺序是[C, A, B, object],调用super().__init__()时会按此顺序依次执行每个类的__init__方法,父类中super().__init__(*args, **kwargs)会继续调用MRO中的下一个类的构造函数。
方案2:遍历父类直接调用构造函数
如果无法修改父类的代码,可以在C的构造函数中遍历所有直接父类,逐个调用它们的构造函数。
修改后的代码:
import inspect class A: def __init__(self): self.atr1 = 'Foo1' class B: def __init__(self): self.atr2 = 'Foo2' class C(A,B): def __init__(self) -> None: # 遍历所有直接父类并调用构造函数 for base in self.__class__.__bases__: base.__init__(self) # 验证代码 fooObj = C() for i in inspect.getmembers(fooObj): if not i[0].startswith('_') and not inspect.ismethod(i[1]): print(i)
输出结果:
('atr1', 'Foo1') ('atr2', 'Foo2')
注意:此方法仅适用于直接父类无多层继承的场景,若父类本身还有父类,可能会导致重复调用或遗漏,因此方案1更通用。
内容的提问来源于stack exchange,提问作者Reza Besharat
相关产品推荐
相关产品推荐

