多继承中super()报错主因是参数未按MRO顺序以keyword-only方式逐级消化:所有类__init__必须用分隔,显式声明所需参数并透传*kwargs,否则导致参数错位、残留或传至object报错。

多继承中 super() 报错,90% 是因为参数没对齐——不是少传了,是没按 MRO 顺序逐级消化、剩余无损传递。
super().__init__() 被报 TypeError: __init__() missing X required keyword-only argument
这是最典型的错误现象:明明传了 country 和 price,却在某个父类里提示缺 currency 或 city。根本原因不是漏写参数,而是某一级 __init__ 没声明自己要的参数为 keyword-only(即用 * 隔开),导致 **kwargs 提前被消耗或关键字冲突。
- 所有参与多重继承链的类,只要接收初始化参数,都必须把「自己负责的参数」声明为 keyword-only,例如
def __init__(self, *, country, city, **kwargs) - 不能写成
def __init__(self, country, city, **kwargs)—— 这会让前序类传来的 positional 参数错位,**kwargs也收不到剩余参数 - 哪怕某个类不接收任何业务参数(比如只做日志或验证),也要写成
def __init__(self, **kwargs)并调用super().__init__(**kwargs),否则链条中断
为什么必须用 **kwargs 而不是显式列全参数
显式列全参数(如 super().__init__(country, city, price, currency))看似直观,但会立刻破坏协作式初始化的可扩展性。一旦新增一个父类或调整 MRO 顺序,所有中间类都要同步改参数列表,极易出错。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
-
**kwargs的作用是「透传」:每个类只取走自己需要的,剩下的原样交给下一个 MRO 类 - MRO 顺序决定谁先拿参数。例如
Flat(Place, Product)的 MRO 是[Flat, Place, Product, object],所以Place.__init__先从**kwargs中取走country和city,再把剩下(含price、currency)传给Product.__init__ - 如果某类忘了用
*声明 keyword-only,它就会把第一个 positional 参数当成自己的,后续类收到的**kwargs就不完整
super() 在 object 层报错:TypeError: object.__init__() takes exactly one argument
这说明参数最终传到了 object.__init__(),但它不接受任何参数(除了 self)。此时问题出在最后一个实际提供逻辑的父类没把多余参数清空,导致 **kwargs 还带着键值对往下传。
- 检查 MRO 最后一个非
object的类(比如上面例子中的Product),确认它是否用完了所有自己声明的参数,并且没把未声明的 key 剩在**kwargs里 - 常见错误:写了
def __init__(self, *, price, **kwargs),但调用时传了currency,而该类没声明currency,于是currency留在**kwargs里,最终传给object.__init__() - 安全做法:在最后一个业务类里,用
kwargs.pop('xxx', default)显式提取,或至少加一句if kwargs: raise TypeError(f"Unexpected kwargs: {list(kwargs)}")快速暴露遗漏
真正难的不是写对某一层 super(),而是确保整条 MRO 链上每个 __init__ 都遵守同一套契约:keyword-only + **kwargs 透传。漏掉任意一环,错误就会出现在看似无关的另一层。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










