super()不是必须但强烈推荐,它按mro链调用下一个类而非父类,混用硬编码会静默中断链或重复执行;所有参与类须统一使用,否则初始化逻辑可能缺失或错乱。

不是“必须”用 super(),而是不用它时,在多重继承中极易出错——而且错误是静默的、难定位的。
直接写 ParentClass.method(self) 会破坏 MRO 链
当你在子类里硬编码父类名调用,比如 A.__init__(self),Python 就完全绕过了方法解析顺序(MRO),直接跳转到那个类执行。这在单继承里看似没问题,但一旦涉及多继承(比如 C(A, B)),就可能:
- A.__init__(self) 和 B.__init__(self) 各自调一次 Base.__init__() → 父类初始化被执行两次
- 或者某一方没写,另一方用了 super() → Base.__init__() 根本不执行
MRO 是动态计算出来的(可通过 C.__mro__ 查看),而硬编码把调用路径锁死了。
super() 不是“调父类”,而是“调 MRO 中下一个类”
这是最容易误解的一点:super() 在 A.__init__() 里,不是去调 A 的父类,而是按 C.__mro__ 找到 A 后面那个类,再调它的 __init__。例如 MRO 是 (C, A, B, Base, object),那么:
- C.__init__() 中的 super().__init__() → 调 A.__init__()
- A.__init__() 中的 super().__init__() → 调 B.__init__()(不是 Base!)
- B.__init__() 中的 super().__init__() → 才调 Base.__init__()
所有参与类都得统一用 super(),链才不断;混用就会跳过中间类或重复执行。
静态方法、类方法里不能直接用 super(),但也不能硬编码父类
在 @staticmethod 或 @classmethod 中,super() 无法自动推导上下文,会报 RuntimeError。这时你得显式传参:
- 类方法中:用 super(cls, cls).classmethod_name()
- 静态方法中:通常不该调用需要实例/类上下文的方法;真要调,得先确认目标方法是否真的不依赖 self 或 cls,否则硬编码父类名反而更危险
硬编码在这里同样脆弱——父类改名、继承结构调整,都会让 Parent.static_method() 失效;而显式 super() 至少还遵循 MRO 原则。
为什么 super() 在 Python 3 中可以不带参数
Python 3 编译器会在函数定义时自动注入当前类和当前实例(或类)作为隐式参数,所以 super() 等价于 super(__class__, self)(实例方法)或 super(__class__, cls)(类方法)。这不是语法糖,而是保证 super() 行为与当前执行位置严格绑定的关键机制。手动写 super(Child, self) 不仅冗余,还容易写错类名或传错对象类型,导致 MRO 查找从错误起点开始。
真正容易被忽略的是:哪怕你只写单继承,只要未来可能被其他类多继承(比如作为 Mixin 被混入),就必须从一开始全链使用 super()。一旦某个中间类漏了,整个链就断了——而这种断裂不会报错,只会让你的初始化逻辑莫名缺失。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











