当父 class 有一个 super() 是什么意思?

What does it mean when a parent class has a super()?

据我所知,super()用于调用subclass中覆盖的方法(就像subclass中覆盖的__init__)。

此外,我知道所有 python class 都继承自一个名为 object 的特殊 class。

在研究OOP时我运行遇到了一个奇怪的例子:

class A(object):
    def __init__(self):
        print('A.__init__')
        super().__init__()

class B(object):
    def __init__(self):
        print('B.__init__')
        super().__init__()

class C(A, B):
    def __init__(self):
        print('C.__init__')
        super().__init__()

除了...我明白了大部分内容...为什么 class A 有一个 super().__init__()?它是父 class,它不应该需要从任何人那里继承。特殊的 object class 什么也没做,所以我不知道为什么需要它。

这不是我在父 class 中看到 super 的唯一情况,在我之前提出的一个问题中,涉及到一个问题的解决方案,但我没有理解它。我也找不到对 super() 继承的这种用法的简单解释。

简单来说...为什么我需要在父 class 中使用 super()

In simple terms...why would i need to use super() in a parent class?

你不知道。除非 parent class 本身是另一个更高 class 的 child,否则没有理由在 parent [=26= 中调用 super() ] 看起来您正在阅读的教程可能不小心 copy/pasted 一些额外的代码。

另一方面,您也不需要 () 括号来定义 class,此外,除非您在 Python2 工作(您不应该在 2020 年工作,因为Python2.x is no longer supported from 2020) 您不需要在 class 名称后面添加 (object),因为这纯粹是 classic Python2 class 的一种方式es 采用新样式格式,但在 Python3 中所有 classes 都是新样式 classes.

因此,上述代码的正确显示方式如下:

class A:
    def __init__(self):
        print('A.__init__')
        # you don't need a super() here as class A isn't inheriting anything

class B:
    def __init__(self):
        print('B.__init__')
        # you don't need the super() here either as B also isn't inheriting anything

class C(A, B):
    def __init__(self):
        print('C.__init__')
        super().__init__()

考虑以下示例:

class A:
    def __init__(self, a, **kwargs):
        print('A.__init__ called')
        self.a = a
        super().__init__(**kwargs)
        print('A.__init__ finished')

class B:
    def __init__(self, b, **kwargs):
        print('B.__init__ called')
        self.b = b
        super().__init__(**kwargs)
        print('B.__init__ finished')

class C(A, B):
    def __init__(self, c, **kwargs):
        print('C.__init__ called')
        self.c = c
        super().__init__(**kwargs)
        print('C.__init__ finished')

创建C对象时,输出如下:

>>> C(a=1, b=2, c=3)
C.__init__ called
A.__init__ called
B.__init__ called
B.__init__ finished
A.__init__ finished
C.__init__ finished
<__main__.C object at 0x7fd15abcab70>

从调用 __init__ 方法的顺序,以及它们以 反向 顺序完成的事实,我们可以看出 C.__init__ 调用 A.__init__,调用 B.__init__。也就是说,尽管 A 没有明确的父级 class(因此它的直接父级是 object),但 A 中的 super().__init__ 调用实际上调用了 B.__init__.

这是因为 BCmethod resolution order (MRO) 中 A 之后的下一个 class。 Aclass需要调用super()因为它的superclass虽然是object,Python允许多重继承,所以A无法保证它是 MRO 中 object 之前的最后一个 class。

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

有关 MRO 和 "cooperative multiple inheritance techniques" 的更详细解释,请参阅 Raymond Hettinger 的文章 Python's super() considered super!