在 Python 中,为啥为没有定义超类的类调用 super() 函数不是错误? [复制]

Posted

技术标签:

【中文标题】在 Python 中,为啥为没有定义超类的类调用 super() 函数不是错误? [复制]【英文标题】:In Python why is calling super() function for a class with no superclass defined is not an error? [duplicate]在 Python 中,为什么为没有定义超类的类调用 super() 函数不是错误? [复制] 【发布时间】:2019-11-05 19:38:10 【问题描述】:

对于 Python 新手,谁能告诉我这里发生了什么?为什么要打印“A init”?

如果我从__init__B 的函数中删除super().__init__() 行,则行为符合预期。但是为什么下面的代码没有错误,我虽然B 没有超类??

class A:

    def __init__(self):
        print("A init")

class B:

    def __init__(self):
        super().__init__()   # why is this line not an error
        print("B init")

class C(B, A):

    def __init__(self):
        super().__init__()
        print("C init")

c = C()

输出

A init

B init

C init

Process finished with exit code 0

【问题讨论】:

在python 3中所有类都继承自object 我明白了。但是当我调用 C 的构造函数时,为什么它打印“A init”,我在想根据 MRO 规则它只会打印“B init”,因为它解析为“最左边的类”?看来 B 的 init 函数正在调用 A 的 init 函数。 我认为C同时调用A和B,多重继承 嗯。根据我的理解,C 应该调用它自己的 init 函数(如果已定义),并且在我的代码中,当我在 C 的 init 中调用 super() 的 init 时,它应该调用 B 的 init,因为 B 是优先级的“超类”(最左边) 因为它 C 被定义为 C(B,A) 顺便说一句,你可以使用这个在线工具来可视化代码执行pythontutor.com/visualize.html#mode=edit 【参考方案1】:

您创建一个C 的实例,我们将其称为self。它的 MRO 为 CBAobject

C__init__ 首次调用super().__init__()。这将委托给 MRO 中下一个类(即 B)中的 __init__使用相同的 self 对象

B__init__ 第一次调用super().__init__()。这将委托给 self 的类 (C) 的 MRO 中的下一个类中的 __init__,即 A

A's __init__ 打印并返回到B's __init__

B's __init__ 打印并返回到C's __init__

C's __init__ 打印并返回到构造函数(object's __new__),它返回self

super() 有两个隐藏参数,__class__(因此它知道在 MRO 中从哪里开始)和self(或cls,对于@classmethods——不管第一个参数是什么,不管名字)。

您必须在 Python 2 中显式提供这些(并且仍然可以),但在 Python 3 中 super() 实际上会检查其调用者的堆栈帧,并在从方法内部调用时找到这些。 (__class__ 变量在方法中隐式可用,并且是定义它的类。)

【讨论】:

以上是关于在 Python 中,为啥为没有定义超类的类调用 super() 函数不是错误? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥在声明子类的对象时会调用超类的构造函数? (爪哇)

Scala的类继承

Swift 继承

类的继承和派生

Java 中的继承——创建子类的对象也会调用超类的构造函数。为啥?

面向对象三大特性