super() 按 MRO 动态调用下一个类方法,而非硬编码父类;必须在 init 首行调用以确保初始化完整,多重继承中所有类须统一使用 super() 才能协作生效。

super() 在 Python 中调用父类方法的正确写法
Python 的 super() 不是“调用父类某个函数”,而是按 MRO(方法解析顺序)委托下一个类的方法。直接写 super().method_name() 才能触发父类逻辑,而不是 ParentClass.method_name(self) —— 后者绕过 MRO,破坏多继承时的协作机制。
常见错误现象:子类重写了 __init__,但忘了调用 super().__init__(),导致父类初始化逻辑完全没执行;或者在多重继承中手动指定父类名,结果在修改类层次后出错。
- 必须传参给
super()的场景极少,绝大多数时候直接用super()(无参数)即可,Python 会自动推导当前类和 self - 如果子类方法签名和父类不一致(比如多了个
debug=False参数),需确保传给super().method_name()的参数仍符合父类定义,否则抛TypeError - 在
@classmethod或@staticmethod中用super()需显式传参:super(ChildClass, cls).class_method()
为什么不能用 ParentClass.method_name(self) 替代 super()
表面看两者都能运行,但本质不同:ParentClass.method_name(self) 是硬编码调用,彻底跳过 MRO;而 super() 是动态查找链上的“下一个”类——这对 __init__、__new__、描述符或 mixin 组合至关重要。
使用场景:你写了一个 JSONSerializableMixin 和一个 ValidatedModel,都重写了 __init__。若各自用 ParentClass.__init__(self),则只有最顶层父类被调一次;用 super().__init__() 才能保证两个 mixin 的初始化逻辑都被执行。
性能影响几乎为零,但可维护性差异极大:一旦父类改名、或中间插入新父类,硬编码写法立刻失效,super() 自动适配。
super() 在 __init__ 中漏调的典型后果
漏掉 super().__init__() 不会报错,但父类中分配的实例属性(如 self._cache、self.config)根本不存在,后续访问直接触发 AttributeError。这种 bug 往往延迟暴露,调试成本高。
容易踩的坑:
- 只在部分分支里调
super().__init__()(比如 if/else 中只有一边有),导致某些路径下父类未初始化 - 在
__init__开头调用了其他方法,而那些方法依赖父类已设置的属性 - 父类
__init__有副作用(如注册信号、打开文件句柄),漏调会导致资源泄漏或状态不一致
建议:把 super().__init__() 放在 __init__ 第一行,除非你明确知道需要先做某些前置检查。
多重继承下 super() 的实际执行顺序
执行顺序由 MRO 决定,不是简单“父类→祖父类”。例如 class C(A, B): pass,其 MRO 是 [C, A, B, object],所以 super().__init__() 在 C.__init__ 中会调 A.__init__,而 A.__init__ 里的 super().__init__() 会继续调 B.__init__,最后到 object.__init__。
验证方式:打印 C.__mro__ 或 C.mro()。如果发现顺序不符合预期,说明类设计违反了“协作式继承”原则——所有参与继承链的类都必须统一使用 super(),不能混用硬编码父类调用。
真正复杂的地方在于:只要有一个类没遵守这个约定,整个链就断裂。这不是语法错误,而是静默的行为偏差,极难定位。

















