用多重继承子适应非合作超类

2024-04-25 11:40:31 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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的初始化行为呢?你知道吗


Tags: 方法self定义initdef情况this适配器
1条回答
网友
1楼 · 发布于 2024-04-25 11:40:31

混合的黄金法则:

总是先从mixin继承。你知道吗


适当的mixin被设计为支持多重继承,即它们有一个带有*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()

class D(B, C): 
    def __init__(self):
        print("D")
        B.__init__(self)
        C.__init__(self)

D()  # output: D B A C

相关问题 更多 >