适应具有多重继承的非合作超类

时间:2018-01-25 22:09:01

标签: python inheritance

假设我使用的库提供以下类:

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 onethis one。从this post开始,我了解为了使合作子类模式起作用,并且C.__init__被调用,BA也需要调用super,将在方法解析顺序中返回C。 Hettinger建议编写一个适配器类来处理这个"非合作的"情况。我可以为B编写一个适配器类,但与Hettinger的例子不同,B是我继承的主要类,而不是mixin。我的理解是我必须重写" B在其适配器中实现的每个方法都可以使用,这似乎是不可行的,特别是如果B是一个可能在将来改变行为的大型库类。

那么有没有办法在不能适应B或A的情况下获得C&C的初始化行为?

1 个答案:

答案 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