假设我使用的库提供以下类:
class A:
def __init__(self):
print("A")
class B(A):
def __init__(self):
print("B")
super().__init__()
然后我定义了一个mixin和一个子类:
class C:
def __init__(self):
print("C")
super().__init__()
class D(B, C):
def __init__(self):
print("D")
super().__init__()
创建新D
的输出是
D
B
A
我的目标是在初始化D时调用C __init__
,无法修改B或A 。期望的输出将是
D
B
A
C
使用super
多重继承有很多问题,例如this one和this one。从this post开始,我了解为了使合作子类模式起作用,并且C.__init__
被调用,B
和A
也需要调用super
,将在方法解析顺序中返回C
。 Hettinger建议编写一个适配器类来处理这个"非合作的"情况。我可以为B编写一个适配器类,但与Hettinger的例子不同,B是我继承的主要类,而不是mixin。我的理解是我必须重写" B在其适配器中实现的每个方法都可以使用,这似乎是不可行的,特别是如果B是一个可能在将来改变行为的大型库类。
那么有没有办法在不能适应B或A的情况下获得C&C的初始化行为?
答案 0 :(得分:2)
mixins的第一大黄金法则:
始终从mixin 首先 继承。
正确的mixins旨在支持多重继承,即它们具有*args, **kwargs
的构造函数,可以调用super().__init__(*args, **kwargs)
(或者它们根本没有构造函数)。像这样的构造函数是完全透明和不明显的;它不会妨碍子类的构造函数。
当子类(D
)调用super().__init__()
时,它将调用mixin的(C
)构造函数,该构造函数将依次调用B
的构造函数。换句话说,只需重新排序D
的父类即可解决您的问题。
class D(C, B):
def __init__(self):
print("D")
super().__init__()
D() # output: D C B A
如果由于某种原因,您必须按照D B A C
的顺序调用构造函数,则应该显式调用父类的构造函数 ,而不是super()
:< / p>
class D(B, C):
def __init__(self):
print("D")
B.__init__(self)
C.__init__(self)
D() # output: D B A C