python - 为什么在多重继承中执行 Base.__init__(self) 而不是 super().__init__() 时会跳过 __init__?

标签 python python-3.x multiple-inheritance super diamond-problem

为什么正是

A.__init__()
B.__init__()
D.__init__()

由以下代码打印?特别是:

  1. 为什么是C.__init__() 打印?

  2. 为什么是C.__init__()如果我把 super().__init__() 打印出来而不是 A.__init__(self) ?

#!/usr/bin/env python3

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

D()

最佳答案

tl;dr:因为B.__init__应该叫C.__init__通过super(B, self).__init__() , 你绕过了那个电话。


为什么不打印 C.__init__()?

因为你没有告诉它。多重继承涉及合作,您使用了显式类引用,否认了合作。

你是否用 super().__init__() 替换了所有“ super 相似”的调用? (因为您已将其标记为 Python 3)您会看到如下输出:

A.__init__()
C.__init__()
B.__init__()
D.__init__()

事实上,如果您只更改 B,您会看到此输出对其中之一的“ super 喜欢”调用:

super(B, self).__init__()
super().__init__()

那么在你的案例中为什么 A 没有给 C 打电话呢?

复制网站上其他地方关于 MRO 的概述清晰的答案是多余的。

如果我使用 super().__init__() 而不是 A.__init__(self) 为什么会打印 C.__init__()?

因为 the no-argument super() goes left to right , 所以 B首先查看,然后在 B 内部使用显式类引用 ( A.__init__(self) )。在这样做的过程中,你失去了 D 作为父类(super class)的所有(大多数*)上下文 C .

super()是什么帮助您导航 MRO,并会让您到达 C.__init__()如果你让它。但是在B你只是在调用 A 的类方法.

*如您所见C.__init__()永远不会被调用。然而,C仍然出现在 D.__bases__ 中:

(<class '__main__.B'>, <class '__main__.C'>)

D.__mro__ :

(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

isinstance(D(), C) is True .

简而言之,Python 知道 CD 的父类(super class), 但你给了 C.__init__然后用你的B.__init__结束运行实现。

关于python - 为什么在多重继承中执行 Base.__init__(self) 而不是 super().__init__() 时会跳过 __init__?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52685876/

相关文章:

long 类型的 Python 对象没有 Len() 错误?

python - Pytest:如何使用从 fixture 返回的列表参数化测试?

python - Pandas - 在数据帧之间查找值并为匹配的系列添加值

python - 根据键列表从字典中获取值

c++ - 如何在没有确切类型信息的情况下从 void* 转换为虚拟基类?

python - 如何为条形图中的不同条形提供十六进制颜色?

python - 从度 >= 3 的节点处分割的图中检索路径

python-3.x - 文件上传 flask 的单元测试用例

java - gwt 接口(interface) HostedModeOptions 扩展了超过 1 个类

c++ - move 构造函数和多重继承