【问题标题】:Python multiple inheritance constructor not called when using super()使用 super() 时未调用 Python 多重继承构造函数
【发布时间】:2014-10-11 22:02:18
【问题描述】:

考虑以下代码:

class A(object):
    def __init__(self):
        pass
class B(object):
    def __init__(self):
        self.something = 'blue'
    def get_something(self):
        return self.something
class C(A,B):
    def __init__(self):
        super().__init__()
        print(self.get_something())

然后做:

c = C()

结果如下:

AttributeError: 'C' object has no attribute 'something'

我想这是因为使用 super() 时没有调用 B 的构造函数。有没有办法使用 Python 3 实现正确的行为?

【问题讨论】:

    标签: python oop inheritance python-3.x multiple-inheritance


    【解决方案1】:

    正如其他人所提到的,方法解析顺序是这里的关键。如果要调用多个超类构造函数,则必须直接调用它们。

    class A(object):
        def __init__(self):
            pass
    class B(object):
        def __init__(self):
            self.something = 'blue'
        def get_something(self):
            return self.something
    class C(A,B):
        def __init__(self):
            A.__init__(self)
            B.__init__(self)
            print(self.get_something())
    

    【讨论】:

    • 感谢您的回答。不过看起来,再调用一次 super() 会更容易。
    • 您的选择。我也只是想展示这个选项,因为这是我的偏好。
    • 如果您的继承层次结构更复杂,这种多重继承风格就会失效。例如,如果AB 都继承自一些常见的Base 类(经典的“钻石”模式)并且都从它们自己的__init__ 方法调用Base.__init__(self),那么Base 类将被初始化两次。如果您改用super,每个__init__ 方法将被调用一次。
    • 在子类中硬编码基类绝对是解决这个问题的错误方法。
    • 如果您的__init__ 方法之一anywhere 接受参数会怎样?或者,如果您从一个存在于您不维护的包中的类继承怎么办?
    【解决方案2】:

    如果它们的子类使用,超类应该使用 super。如果您将 super().__init__() 行添加到 A 和 B 中,您的示例应该可以再次工作。

    查看C的方法解析顺序:

    >>> C.mro()
    [__main__.C, __main__.A, __main__.B, builtins.object]
    

    This article 应该把事情弄清楚。

    【讨论】:

      猜你喜欢
      • 2016-04-25
      • 1970-01-01
      • 2015-06-29
      • 2013-09-06
      • 2017-07-30
      • 2018-12-08
      • 2017-08-10
      • 2018-10-10
      相关资源
      最近更新 更多