python - 用多重继承调用父类__init__,正确的方法是什么?

标签 python oop inheritance multiple-inheritance super

假设我有多个继承方案:

class A(object):
    # code for A here

class B(object):
    # code for B here

class C(A, B):
    def __init__(self):
        # What's the right code to write here to ensure 
        # A.__init__ and B.__init__ get called?


编写C__init__有两种典型方法:


(旧式)ParentClass.__init__(self)
(较新样式)super(DerivedClass, self).__init__()


但是,无论哪种情况,如果父类(ABdon't follow the same convention, then the code will not work correctly(某些类可能会丢失,或者被多次调用)。

那么又是什么正确的方法呢?说“保持一致,遵循一个或另一个”很容易,但是如果AB来自第三方库,那又会怎样呢?有没有一种方法可以确保所有父类构造函数都被调用(以正确的顺序,并且只能调用一次)?

编辑:看看我的意思,如果我这样做:

class A(object):
    def __init__(self):
        print("Entering A")
        super(A, self).__init__()
        print("Leaving A")

class B(object):
    def __init__(self):
        print("Entering B")
        super(B, self).__init__()
        print("Leaving B")

class C(A, B):
    def __init__(self):
        print("Entering C")
        A.__init__(self)
        B.__init__(self)
        print("Leaving C")


然后我得到:

Entering C
Entering A
Entering B
Leaving B
Leaving A
Entering B
Leaving B
Leaving C


请注意,B的init被调用两次。如果我做:

class A(object):
    def __init__(self):
        print("Entering A")
        print("Leaving A")

class B(object):
    def __init__(self):
        print("Entering B")
        super(B, self).__init__()
        print("Leaving B")

class C(A, B):
    def __init__(self):
        print("Entering C")
        super(C, self).__init__()
        print("Leaving C")


然后我得到:

Entering C
Entering A
Leaving A
Leaving C


请注意,永远不会调用B的init。因此,似乎除非我知道/控制我从中继承的类(AB)的初始化,否则我无法对正在编写的类(C)做出安全的选择。

最佳答案

两种方式都可以正常工作。使用super()的方法为子类带来了更大的灵活性。

在直接调用方法中,C.__init__可以同时调用A.__init__B.__init__

使用super()时,需要将这些类设计为协作多重继承,其中C调用super,这将调用A的代码,该调用还将调用super,这将调用B的代码。有关使用super可以执行的操作的更多详细信息,请参见http://rhettinger.wordpress.com/2011/05/26/super-considered-super

[回答问题,稍后编辑]


  因此,似乎除非我知道/控制类的初始化,否则,
  继承自(A和B)我不能为自己所在的班级做出安全的选择
  写作(C)。


参考的文章显示了如何通过在AB周围添加包装器类来处理这种情况。标题为“如何合并非合作类”的部分提供了一个可行的示例。

可能希望多重继承更容易,让您毫不费力地组合Car和Airplane类来获得FlyingCar,但现实情况是,单独设计的组件通常需要适配器或包装器,然后才能像我们希望的那样无缝地组装在一起:-)

还有一种想法:如果您不满意使用多重继承来编写功能,则可以使用composition来完全控制在哪些情况下调用哪些方法。

关于python - 用多重继承调用父类__init__,正确的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55549401/

相关文章:

oop - 绕过 "moving out of borrowed self"检查器的首选模式

java - 如何扩展 JPA 实体以仅添加组合

python - 在 OSX 10.8.2 上使用 Python 2.7 获取适用于 Google App Engine 的 AppTrace

python - 如果 name = hash 则自动填充

Python pandas,将一个表中的多列与另一表中的单列合并

python - @asyncio.coroutine 与 async def

java - 类的结构

java - 理想的代码遵循德米特法则并且是可测试的(依赖注入(inject))?

c++ - C++11中私有(private)继承聚合类的类的聚合初始化

c# - 为什么泛型类型参数中的隐式子到父转换是不可能的?