【问题标题】:How does Python 3 super() work in this particular multiple inheritance situation? [duplicate]Python 3 super() 如何在这种特殊的多重继承情况下工作? [复制]
【发布时间】:2016-09-10 06:06:41
【问题描述】:

我有以下代码:

class A:
    def __init__(self):
        print("A.__init__")

class B(A):
    def __init__(self):
        print("B.__init__")
        super().__init__()

class C(A):
    def __init__(self):
        print("C.__init__")
        super().__init__()


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

当我从 D 类中实例化一个对象时,

d = D()

我明白了:

>>> d = D()
D.__init__
B.__init__
C.__init__
A.__init__

为什么 A 类的 __init__() 只被调用一次,而且在最后?注意 B 类和 C 类都称为 A 类的 __init__(),所以我希望 A 类的 __init__() 应该被调用两次。

我阅读了 Python 3 的文档和 Hettinger 先生的博客,但没有弄清楚底层机制。那么super()是如何确定它只需要执行一次的呢?谢谢。

【问题讨论】:

  • 能否请反对者解释一下为什么您反对我的问题?我真的不明白。谢谢
  • 每个方法都调用super().__init__() A.__init__()。为什么你认为A.__init__ 在这些情况下是同一个东西?
  • super() 查看 MRO 类(方法解析顺序)。对于多重继承(菱形继承图),MRO 仍将是线性,正是为了避免多次调用A.__init__()。查看D.__mro__ 以查看在运行时确定的实际MRO,您会看到它是[D, B, C, A]。阅读Python MRO documentation 了解原因和方法。

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


【解决方案1】:

Python 有一种称为方法解析顺序 (MRO) 的机制,可以在类层次结构中找到合适的方法。 MRO中有两条规则:

1- 部门优先从左到右搜索

2- 只考虑最后一次出现的类

现在回到你的例子:

我。搜索从 D 开始,将其添加到 MRO 列表 [D]。

二。 D类继承自B和C。B是最左边的父类,然后是C。所以MRO列表变为[D,B,C]。

三。然后搜索继续到更深层次,是 B 的父级,并且 A 被添加到列表中。现在我们有 [D, B, C, A]。 继续搜索 C 的父母,再次是 A。由于 A 已经在列表中,因此没有任何变化。

四。搜索进入更深层次(A 的父级),因为 A 没有任何明确的父级,所以搜索到此结束。

所以最终的列表是 [D, B, C, A]。

super() 方法使用这个列表来完成它的工作,这就是为什么最后调用 A

【讨论】:

  • 感谢您的回答。我在理解你的第 2 点时遇到了一些麻烦(只考虑最后一次出现的课程)。当您说“发生”时,您指的是什么?调用它的方法算作一次事件吗?在我的例子中,我可以说 A 类发生了两次吗?非常感谢。
  • 当搜索过程访问一个类时,它需要将它添加到列表中,但如果该类已经添加,则将其删除,然后添加到列表的后面。因此可以保证每个类只添加到 MRO 列表中一次,并且该类最后一次出现在搜索过程中很重要。希望这有助于@JinghuiNiu
  • @Farzan Hajian 我这里有后续,如果我确实需要在 B 和 C 中调用 A 类的 __init__() 两次怎么办? MRO 会机械地忽略我的请求,而不管情况如何都只调用一次?那么有没有办法克服呢?
  • @JinghuiNiu class A的__init__()无论在搜索中出现多少次都会被调用一次,不幸的是我不知道任何解决方法。
  • @Farzan 我还在研究你的评论,如果我们为每个类的 __init__() 切换 print() 行和 super() 行,我实际上得到了一个反向序列,即 [ A, C, B, D],而不是 [D,B,C,A]。这里发生了什么??就是想不通。
猜你喜欢
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 2018-01-04
  • 2020-10-07
  • 2020-09-26
  • 2018-01-27
相关资源
最近更新 更多