Python中的super().__init__()用法详解
前言写子类时很多人会习惯性地在__init__里加一句super().__init__()问为什么答「网上都这么写」。这句到底在做什么、什么时候会出错、多重继承下为什么顺序和你以为的不一样往往说不清楚。先纠正一个流传极广的说法super()返回的不是「父类」。官方文档的措辞是——它返回一个代理对象把方法调用委托给某个类的父类或兄弟类具体委托给谁由object_or_type的方法解析顺序MRO, Method Resolution Order决定搜索从type之后的那一个类开始。也就是说super()找的是「MRO 里的下一个」而不是「我的直接父类」。单继承场景下这两者恰好重合所以这个误解一直没被发现直到遇上多重继承。还有一个必须点明的版本差异零参数的super()是 Python 3 才有的写法。Python 2 里必须写成super(ClassName, self).__init__()而且对老式类classic class根本不能用。Python 2.7 已于2020 年 1 月 1 日停止维护PEP 373所以本文一律用 Python 3 的零参写法看到super(C, self)的老代码知道它是 2 时代的产物即可。本文只讲super().__init__()这一件事为什么需要它、super()到底返回什么、零参形式凭什么能工作、多重继承下怎么协作以及忘了调用时会发生什么。一、为什么要在子类里调用父类的 __init____init__不是构造对象的唯一环节真正创建实例的是__new__但它是绑定实例属性的地方。子类如果定义了自己的__init__它就完全覆盖了父类的同名方法——Python 不会自动帮你把父类那份也跑一遍。# 适用于 Python 3.8class Animal:def __init__(self, name):self.name nameclass Dog(Animal):def __init__(self, name, breed):self.breed breed # 只绑定了自己的属性d Dog(旺财, 柴犬)print(d.breed) # 柴犬print(d.name) # AttributeError: Dog object has no attribute nameDog的__init__一写Animal.__init__就再也不会自动执行self.name从来没被赋过值。这就是「忘了调super().__init__()」最直接的后果属性缺失而且报错发生在离出错点很远的地方——你在d.name那一行才看到AttributeError很难联想到是构造函数没串起来。补上之后就正常了# 适用于 Python 3.8class Dog(Animal):def __init__(self, name, breed):super().__init__(name) # 先让父类把 name 绑好self.breed breed顺序上建议先调用父类初始化再设置子类自己的属性。反过来的话如果父类的__init__也要写同一个属性名你子类的赋值会被父类覆盖掉症状同样隐蔽。二、super() 的真正含义MRO 里的「下一个」super()的官方签名是class super(type, object_or_typeNone, /)文档给了一个非常清晰的例子如果object_or_type的__mro__是D - B - C - A - object而type是B那么super()搜索的范围就是C - A - object。它跳过的是B自己从B的下一个开始找而不是从「B 的父类」找。MRO 可以用类.__mro__或等价的类.mro()查看# 适用于 Python 3.8class A:passclass B(A):passclass C(A):passclass D(B, C):passfor cls in D.__mro__:print(cls.__name__)打印顺序是D、B、C、A、object。Python 用的是C3 线性化算法官方文档说明它「即使在钻石型继承结构下也能正确工作」。这个顺序不是凭感觉排的它保证了两件事每个类只出现一次且子类永远排在父类之前。理解这一点后super().__init__()的准确含义就是在这条 MRO 链上从当前类往后的第一个定义了__init__的类。单继承时它是父类多重继承时它可能是「兄弟类」。三、零参 super() 为什么能在方法里工作这是最让人困惑的一点super()明明是零参数它怎么知道当前类是谁、当前实例是谁答案是编译器的隐式闭包。官方文档语言参考的「创建类对象」一节写道__class__是编译器在类体里创建的一个隐式闭包引用——只要类体中任何方法引用了__class__或super编译器就会创建它。这样零参super()就能通过词法作用域确定「正在定义的是哪个类」而「当前实例」则取自紧邻外层函数的第一个参数通常叫self。由此推出几个直接结论零参super()只能在类体内的普通方法里用。写在模块顶层、或者写在一个不属于任何类的函数里都会报RuntimeError: super(): no arguments。它在嵌套函数里不能如预期工作包括生成器表达式——因为那些东西会隐式创建一层新的函数作用域第一参数不再是self。官方文档对此有明确提示。需要跨作用域时就用两参形式把话说死super(Dog, self).__init__(name)。两参形式不限于方法内使用在任何地方都能用只要你把类与实例写清楚。# 适用于 Python 3.8class A:def __init__(self, x):self.x xclass B(A):def __init__(self, x):# 两参形式明确指定「从 B 之后开始找」super(B, self).__init__(x)# 上面这行与零参的 super().__init__(x) 等价在 3 里既然等价为什么还推荐零参因为类名改了不用同步改代码减少了漏改的风险——这正是零参形式被设计出来的动机。四、协作式多重继承菱形结构怎么走多重继承里每个__init__都调用super().__init__()整条 MRO 链就会被完整地、每个类恰好一次地走一遍。这种写法叫协作式cooperative继承。它要求每个类都用同样的调用约定把不认识的参数原样往上传。# 适用于 Python 3.8class Base:def __init__(self, **kwargs):print(Base.__init__, kwargs)super().__init__() # 这里之后就是 object链路到此结束class Logger(Base):def __init__(self, *, verboseFalse, **kwargs):super().__init__(**kwargs)self.verbose verboseclass Storage(Base):def __init__(self, *, path, **kwargs):super().__init__(**kwargs)self.path pathclass App(Logger, Storage):def __init__(self, name, **kwargs):super().__init__(**kwargs)self.name nameapp App(demo, verboseTrue, path/tmp/data)print(app.name, app.verbose, app.path)App.__mro__是App - Logger - Storage - Base - object。App.__init__调super().__init__(**kwargs)进到LoggerLogger处理后把剩下的**kwargs继续传给super().__init__进到StorageStorage再传到BaseBase最后调super().__init__()时指向objectobject.__init__()不接受额外参数但这时kwargs已经是空的所以平安通过。这里有三条硬约束每个类都要调super().__init__()链一断后面的类就全被跳过。每个类都要把多余的参数用**kwargs传下去否则下游类拿不到它需要的参数。keyword-only 参数*后面那些是这套约定的好帮手它让「谁消费哪个参数」一目了然也避免了位置参数顺序被打乱。对比一下「不协作」的写法问题就很明显# 适用于 Python 3.8class App2(Logger, Storage):def __init__(self, name, verbose, path):Logger.__init__(self, verboseverbose) # 显式点名Storage.__init__(self, pathpath) # 也显式点名self.name name这种写法在简单场景下能用但它绕开了 MRO一旦Logger和Storage有共同祖先那个祖先的__init__会被执行两次。菱形继承里这是典型 bug——初始化做了两遍注册回调重复、连接被建了两次、计数器翻倍而报错信息通常完全指不到这里。五、object.__init__ 的边界链路最后一定会走到object。官方文档对object的描述是它的构造函数不接受任何参数。所以在协作式链里Base那一层必须先把自己认识的参数全部消费掉才能用空参数调用super().__init__()。反过来如果你在调用时把多余的参数一路传到object就会得到TypeError# 适用于 Python 3.8class Bad:def __init__(self, **kwargs):super().__init__(**kwargs) # kwargs 非空时object 会拒绝class Sub(Bad):def __init__(self):super().__init__(unknown1) # TypeError: object.__init__() takes exactly one argument# Sub() # 取消注释就会看到上面那个 TypeError这个报错的措辞乍看莫名其妙明明是子类在传参但知道它是object发出来的就明白问题出在「没人消费unknown这个参数」。另外super()在 Python 3.14 起还支持被pickle和copy这是历史遗留的限制被解除日常几乎用不到知道即可。常见坑点1. 子类写了__init__却忘了调super().__init__()。❌class Dog(Animal): def __init__(self, breed): self.breed breed—— 父类属性全丢之后某处d.name抛AttributeError。 ✅ 第一句写super().__init__(name)把父类的初始化接上。2. 以为super()就是「我的父类」。❌ 多重继承里指望super()一定指向直接父类。 ✅ 它指向MRO 里当前类的下一个用类.__mro__看真实顺序别猜。3. 在嵌套函数或生成器表达式里用零参super()。❌ 在方法内部定义一个函数里面写super().__init__()—— 外层函数的第一个参数不再被当作self行为不符合预期。 ✅ 要么把super()调用挪回方法体内要么改成两参形式super(CurrentClass, self)。4. 在模块顶层或类外的函数里用零参super()。❌super().__init__()写在类外面 ——RuntimeError。 ✅ 零参super()只适用于类体内的普通方法其他位置用两参形式。5. 多重继承里显式点名调用父类方法。❌Logger.__init__(self, ...)与Storage.__init__(self, ...)并列 —— 共同祖先被初始化两次。 ✅ 统一用super().__init__(**kwargs)让 MRO 决定顺序保证每个类只跑一次。6. 协作链里吞掉了**kwargs。❌def __init__(self, *, path, **kwargs): super().__init__()—— 直接把**kwargs丢了下游类拿不到自己的参数。 ✅super().__init__(**kwargs)把不认识的原样传下去。7. 把参数一路传到object。❌ 最底层没有消费掉剩余参数就super().__init__(**kwargs)——TypeError: object.__init__() takes exactly one argument。 ✅ 链的末端用空参数调用super().__init__()确认没有参数剩下。8. 照抄 Python 2 的super(C, self)却没注意类名。❌ 类重命名后老代码里super(OldName, self).__init__()还在 —— 直接NameError或者行为错乱。 ✅ Python 3 用零参super()super(C, self)那种写法是 Python 2 时代必需的2.7 已于 2020-01-01 停止维护新代码不必再写。总结疑问答案super()返回什么一个代理对象按 MRO 找类找的范围从当前类在 MRO 中的下一个开始零参形式凭什么能工作编译器为类体创建隐式__class__闭包引用零参形式的限制只能在类体内的普通方法里用嵌套函数里不按预期工作单继承要注意什么子类写了__init__就必须调用父类的多重继承要注意什么每层都调super().__init__(**kwargs)并透传参数为什么不能点名调用父类菱形结构下会导致共同祖先被初始化多次链路终点object.__init__()不接受参数末端必须空参调用Python 2 对照super(C, self).__init__()是 2 时代的必需写法super().__init__()这一行代码背后的模型其实只有一条主线Python 的继承查找是一条线性化的 MRO 链super()就是「沿链往下走一格」。单继承时它看起来像「调用父类」多重继承时它变成「调用下一个协作伙伴」。把「父类」这个词从脑子里换掉菱形继承下的种种怪现象就都能解释了。

相关新闻

深度学习YOLOv8工地检测裸土是否覆盖数据集 建筑工地裸土未覆盖检测数据集 识别判定裸土覆盖的检测,智慧化建筑工地

深度学习YOLOv8工地检测裸土是否覆盖数据集 建筑工地裸土未覆盖检测数据集 识别判定裸土覆盖的检测,智慧化建筑工地

使用深度学习YOLOv8训练用于工地检测裸土是否覆盖数据集模型 ,通过训练建筑工地裸土未覆盖检测数据集 识别判定裸土覆盖的检测 文章目录使用深度学习YOLOv8训练用于工地检测裸土是否覆盖数据集模型 ,通过训练建筑工地裸土未覆盖检测数据集 识别判定裸土覆…

2026/10/12 20:43:22 阅读更多 →
pstack-claude:进程栈跟踪驱动的AI编程辅助工具

pstack-claude:进程栈跟踪驱动的AI编程辅助工具

1. 项目概述:pstack-claude 是什么,它解决的是哪类开发者的真实痛点?“pstack-claude”这个名称乍看像一个工具组合词,但拆解后立刻能抓住核心脉络:pstack是 Linux 系统中用于快速抓取进程调用栈的轻量级诊断命令&…

2026/10/12 22:53:06 阅读更多 →
pstack-claude:本地化AI调试代理,让Claude实时分析进程调用栈

pstack-claude:本地化AI调试代理,让Claude实时分析进程调用栈

1. 项目概述:pstack-claude 是什么,它解决的是哪类开发者的实际痛点?pstack-claude 这个名字乍看像一个工具组合词,但拆解后立刻能抓住核心脉络:pstack是 Linux 系统中用于打印进程调用栈(process stack&am…

2026/10/12 4:41:57 阅读更多 →

最新新闻

Clover_v5.0_r5122_X64黑苹果引导实战:从U盘制作到多系统配置

Clover_v5.0_r5122_X64黑苹果引导实战:从U盘制作到多系统配置

简介:Clover_v5.0_r5122_X64 是一款面向黑果(Hackintosh)爱好者的四叶草启动引导程序,专为64位体系结构设计,核心作用是模拟苹果原生启动管理器,让非苹果硬件也能识别并加载 macOS 内核,尤其适配…

2026/10/13 7:21:01 阅读更多 →
后端程序注册Windows服务:sc.exe与NSSM实操指南

后端程序注册Windows服务:sc.exe与NSSM实操指南

最近帮一个朋友迁移旧项目,对方有一台还在服役的 Windows Server 2012 服务器,上面跑着几个内部用的后端程序。因为平时是人工启动、命令行窗口挂着,结果清明假期服务器半夜自动更新重启了一次,第二天业务系统全部瘫痪&#xff0c…

2026/10/13 7:21:01 阅读更多 →
人生噪音断舍离:像庖丁解牛一样清理信息过载与情绪内耗

人生噪音断舍离:像庖丁解牛一样清理信息过载与情绪内耗

人生噪音断舍离的庖丁解牛你有没有过这样的状态?手机里躺着上千条未读消息,通讯录里堆着几百个根本想不起是谁的联系人,订阅号每天刷出几十篇“不看就亏”的文章,桌面上摆满了“以后可能用得上”的杂物,脑子里同时转着…

2026/10/13 7:21:01 阅读更多 →
仿Hypixel起床战争服务端搭建指南:Paper插件开发核心思路与避坑实践

仿Hypixel起床战争服务端搭建指南:Paper插件开发核心思路与避坑实践

简介:一套面向《我的世界》服务器管理与联机爱好者的仿Hypixel起床战争(BedWars)服务端资源包,适合希望搭建多人竞技小游戏服、体验起床战争玩法的玩家或服主使用。资源为ZIP压缩包,共663个文件,约393.29MB…

2026/10/13 7:21:01 阅读更多 →
多Agent串行流水线:从任务拆解到断点续跑的工程实践

多Agent串行流水线:从任务拆解到断点续跑的工程实践

先说一个很多人都会踩的坑:你以为把任务丢给一个大模型,加上上下文提示词,它就能帮你把一个十步的活儿一口气干完。实际上,大模型单次输出经常在中间某个环节悄悄跑偏,或者直接因为超过了输出上限给你半截结果。一旦出…

2026/10/13 7:21:01 阅读更多 →
85GB期货TICK数据处理实战:清洗、加载与特征工程

85GB期货TICK数据处理实战:清洗、加载与特征工程

简介:本资源提供2013至2015年国内期货市场高频TICK级原始行情数据的种子文件集合,面向量化交易研究者、金融工程学习者及算法交易开发者,用于回测策略、构建tick级价量模型或训练时序预测模型。资源包共335个文件,主体包含108个Py…

2026/10/13 7:20:01 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →