super() 不避免重复初始化,它只按 mro 调用下一个类的 init__;重复与否取决于是否显式调用父类 __init 及是否多处触发。

直接说结论:super() 本身不会“避免重复初始化”,它只是按 MRO 调用下一个类的方法;重复初始化是否发生,取决于你**在子类 __init__ 中是否显式调用了父类 __init__,以及父类 __init__ 是否被多次触发**。
为什么 super() 有时反而导致重复初始化?
常见错误是子类里既写了 super().__init__(),又手动调用了 Parent.__init__(self, ...) —— 这会让父类初始化执行两次。更隐蔽的情况是多个父类都调用了同一个基类的 __init__,而没用 super() 协调(即未遵循 cooperative inheritance)。
- 多重继承下,若所有父类都用
super().__init__(),Python 会按 MRO 顺序逐个调用,每个只执行一次 - 只要有一个父类写成
Parent.__init__(self, ...),就绕过 MRO,破坏协作链,可能跳过某些初始化,或在别处重复触发 -
super()在__init__中不是“调用父类”,而是“调用 MRO 中下一个类”的方法 —— 它不认“父”,只认“下一个”
正确写法:所有参与继承链的类都必须用 super()
哪怕只有单继承,也建议统一用 super(),为将来扩展多重继承留余地。关键是:所有类的 __init__ 都要接受并传递 **kwargs(或至少把未处理的参数转交),否则 MRO 链会在某处中断。
class A:
def __init__(self, x, **kwargs):
super().__init__(**kwargs) # 即使 A 是顶层,也要 super()
self.x = x
<p>class B:
def <strong>init</strong>(self, y, <strong>kwargs):
super().<strong>init</strong>(</strong>kwargs)
self.y = y</p><p>class C(A, B):
def <strong>init</strong>(self, x, y, z):
super().<strong>init</strong>(x=x, y=y, z=z) # 把参数全打包传下去
self.z = z
</p>
注意:C 的 __init__ 没有硬编码调用 A 或 B,而是靠 super() 和 **kwargs 自动流转;A 和 B 各取所需参数,多余参数继续往上传,直到 object.__init__() 接收空参结束。
调试重复初始化:看 MRO 和实际调用路径
如果发现某个 __init__ 被执行了两次,先查 MRO 是否合理,再加日志确认调用链:
- 打印
C.__mro__看顺序:(C, A, B, object)是预期顺序;若出现A在B前但B.__init__却先被调,说明某处没走super() - 在每个
__init__开头加print(f"enter {self.__class__.__name__}"),运行时观察输出次数和顺序 - 检查是否在子类中误写了
A.__init__(self, ...)—— 这种写法会跳过super()机制,且无法与B协作
最容易被忽略的点:顶层基类(比如 A)也必须写 super().__init__(**kwargs),哪怕它看起来“没父类”。因为 object.__init__() 确实存在,且需要被干净调用;漏掉它,**kwargs 会在某一层卡住,后续类收不到参数,可能静默失败或报错。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











