Python 多重继承混乱

Python multiple inheritance confusion

我一直在努力了解如何在编写继承自两个 不相关的 的 class 时确保所有 super().__init__() 的 运行 ] classes。根据 this 和其他类似答案,调用 super(DerivedClass, self).__init__() 应该可以解决问题(“较新的样式”)。

所以我设置了一个虚拟示例:

class One():
    def __init__(self):
        print("One runs")
        self.one = 1
        
class Two():
    def __init__(self):
        print("Two runs")
        self.two = 2
        
        
class Three(One, Two):
    def __init__(self):
        super(Three, self).__init__()
        print("Three runs")

three = Three()
print(three.two)

令我最惊讶的是,当 运行ning 在 Python 3.9.7 上时,这会导致错误。我得到的确切输出是:

One runs
Three runs
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/var/folders/xd/f8xs148x2j18h636phmf27zh0000gq/T/ipykernel_7384/3344160392.py in <module>
     16 
     17 three = Three()
---> 18 print(three.two)

AttributeError: 'Three' object has no attribute 'two'

这让我非常困惑。这不是用“新风格”做的正确方法吗?我错过了什么?

每个__init__不是运行,因为你没有正确使用super。在设计使用 super 的 class 层次结构时,重要的是 所有 class 都使用它。

class One:
    def __init__(self):
        super().__init__()
        print("One runs")
        self.one = 1
        
class Two:
    def __init__(self):
        super().__init__()
        print("Two runs")
        self.two = 2
        
        
class Three(One, Two):
    def __init__(self):
        super().__init__()
        print("Three runs")

虽然继承图是有向无环图,但方法解析顺序是该树中节点的线性排序。 super 在确定通过 super().

调用哪个方法时使用该列表,而不是图形本身
>>> Three.mro()
[<class '__main__.Three'>, <class '__main__.One'>, <class '__main__.Two'>, <class 'object'>]

Three() 调用 Three.__init__,后者调用 One.__init__,后者调用 Two.__init__,后者调用 object.__init__,后者什么也不调用,因为 object.__init____init__.

的链顶

可以在 Python's super() considered super! 中找到更多详细信息,其中还提供了有关如何在尚未使用 super 时调整 OneTwo 的建议。