我有下面的班级结构。只需忽略一些小问题,例如传递错误的变量名称,这不是这里的问题,我稍后会解释问题是什么。
class A:
def __init__(self, a, b, c, d=0, e=0, f=0):
self.a = a
self.b = b
self.c = c
self.d = d
self.e = e
self.f = f
class B(A):
def __init__(self, a, b, c, d, **kwargs):
super().__init__(a, b, d, **kwargs)
# A.__init__(self, a, b, d, **kwargs)
self.c = c
class C(A):
def __init__(self, a, b, c, d, **kwargs):
super().__init__(a, b, d, **kwargs)
# A.__init__(self, a, b, d, **kwargs)
self.c = c
class D(B, C):
def __init__(self, a, b, c, d, e, **kwargs):
super().__init__(a, b, c, e, **kwargs)
# B.__init__(self, a, b, c, e, **kwargs)
C.__init__(self, a, b, d, e)
class E(D):
def __init__(self, a, b, c, d, e=0, **kwargs):
super().__init__(a, b, c, d, e, **kwargs)
# D.__init__(self, a, b, c, d, e, **kwargs)
if __name__ == '__main__':
E(None, None, None, 0)
当我运行此代码时,它给出以下错误:
Traceback (most recent call last):
File "/Users/user/Library/Application Support/JetBrains/PyCharm2023.2/scratches/scratch_5.py", line 39, in <module>
E(None, None, None, 0)
File "/Users/user/Library/Application Support/JetBrains/PyCharm2023.2/scratches/scratch_5.py", line 34, in __init__
super().__init__(a, b, c, d, e, **kwargs)
File "/Users/user/Library/Application Support/JetBrains/PyCharm2023.2/scratches/scratch_5.py", line 27, in __init__
super().__init__(a, b, c, e, **kwargs)
File "/Users/user/Library/Application Support/JetBrains/PyCharm2023.2/scratches/scratch_5.py", line 13, in __init__
super().__init__(a, b, d, **kwargs)
TypeError: C.__init__() missing 1 required positional argument: 'd'
但是,如果我用第一个
super().__init__()
替换每个 superclass.__init__
调用(这显然不是同一件事,否则两种情况都会失败),那么它工作得很好。
要使其工作,只需取消所有
super().__init__()
调用的注释并取消所有注释行的注释,它就会完美地工作。问题是为什么这两种情况都没有失败? super().__init__
的工作方式有何不同? super()
不解析为第一个超类吗?下面简化的逻辑有错吗?
class A(B, C)
def __init__():
super().__init__() # is this not equivalent to B.__init__()?
Python
super
很时髦;它会按照 type(self)
的方法解析顺序(MRO)找到下一个类,而不是您所说的第一个“超类”。
当您在
super().__init__
中调用 B.__init__
时,super
会在 self
的 MRO 中查找下一个类别,其类型为 E
。如果你看一下E.__mro__
,它就像:
(<class '__main__.E'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
这里
B
之后的类是C
,所以称为C.__init__
。
super
的官方 Python 文档中。
回答您的编辑:简化的逻辑是正确的。然而,Python 查找
super().__init__
inside B.__init__
的方式并不是您所期望的方式。