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

Why is an __init__ skipped when doing Base.__init__(self) in multiple inheritance instead of super().__init__()?

究竟为什么

1
2
3
A.__init__()
B.__init__()
D.__init__()

按以下代码打印?特别地:

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

  • 如果我把super().__init__()而不是A.__init__(self),为什么要打印C.__init__()

  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #!/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__是通过super(B, self).__init__()被称为C.__init__的,而你没有打这个电话。

    为什么不打印c.u init_uu()?

    因为你没有告诉我。多重继承涉及合作,并且您已经使用了显式的类引用,拒绝了合作。

    如果您用super().__init__()替换了所有"super-like"调用(因为您已经将其标记为python 3),您将看到如下输出:

    1
    2
    3
    4
    A.__init__()
    C.__init__()
    B.__init__()
    D.__init__()

    事实上,如果您只更改B的"super like"调用,您将看到这个输出:

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

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

    复制网站上其他地方关于MRO的详细答案是多余的。

    • python的super()如何处理多重继承?
    • python的"super"如何做正确的事情?

    如果我把super()而不是"init"(self),为什么要打印c.u init_uu()?

    因为no-argument super()从左向右,所以首先查看B,然后在b中使用显式类引用(A.__init__(self))。在这样做的过程中,你会失去所有(大多数)的上下文,这也是d作为一个超类C所拥有的。

    super()是帮助您导航MRO的工具,如果您允许的话,您将可以到达C.__init__()。但是在B中,您只是调用A的一个classmethod。

    *正如你所注意到的,C.__init__()从来没有被调用过。然而,C仍出现在D.__bases__中:

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

    D.__mro__中:

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

    isinstance(D(), C) is True

    简而言之,python知道CD的一个超类,但是您给出了C.__init__并使用B.__init__实现结束运行。