类可以与 SuperClass.__init__() 一起使用,但不能与 super().__init__() 一起使用

问题描述 投票:0回答:1

我有下面的班级结构。只需忽略一些小问题,例如传递错误的变量名称,这不是这里的问题,我稍后会解释问题是什么。

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 oop inheritance multiple-inheritance
1个回答
0
投票

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__
的方式并不是您所期望的方式。

© www.soinside.com 2019 - 2024. All rights reserved.