为什么恰好是
A.__init__()
B.__init__()
D.__init__()
按以下代码打印?特别是:
为什么C.__init__()
未打印?
为什么我放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()
答案 0 :(得分:6)
B.__init__
调用C.__init__
来调用super(B, self).__init__()
,所以您绕过了该调用。为什么不打印C .__ init __()?
因为您没有告诉。多重继承涉及合作,您已经使用了显式的类引用来拒绝这种合作。
如果您用super().__init__()
替换了所有“超级类”调用(因为您已将其标记为Python 3),您将看到如下输出:
A.__init__()
C.__init__()
B.__init__()
D.__init__()
实际上,如果仅将B
的“超级类”调用更改为以下任何一个,就会看到此输出:
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 也作为超类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 知道 C
是D
的超类,但是您给了C.__init__
并以{{1} }实施。