尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
深入了解Python的继承
前言继承inheritance是 Python 里最常用的代码复用手段之一把一组类共有的属性和方法抽到一个基类base class也叫父类里其余类通过class Child(Base)声明自己是它的子类subclass从而自动获得基类的一切。很多人对继承的理解停在子类能用父类的方法这一层于是遇到下面这些问题就懵了为什么改了子类的类属性父类也变了为什么子类__init__忘了调super()之后父类的状态全是空的为什么多重继承里方法调用的顺序跟写代码的顺序不一样这些问题的答案都藏在属性查找过程和方法解析顺序MRO里。本文从继承时解释器到底做了什么讲起重点讲清属性查找、super()的行为以及实际开发中最该注意的几条边界。一、继承做了什么属性查找的两步走声明class Dog(Animal): ...之后Python 会把Animal放进Dog.__bases__并让Dog的实例在找不到某个属性时沿着基类链继续找。具体查找分两步先在实例自己的__dict__里找找不到再到类及其基类里找。类属性的查找走 MRO。理解这两步就理解了类属性 vs 实例属性的全部差异。# 适用于 Python 3.8class Animal:kind animal # 类属性def __init__(self, name):self.name name # 实例属性class Dog(Animal):passd Dog(旺财)print(d.name) # 旺财print(d.kind) # animal —— 从基类 Animal 找到d.kind并不是d自己的属性而是顺着Dog - Animal找到的类属性。一旦执行d.kind dogPython 会在实例字典里新建一个kind从此遮蔽shadow掉类里的那个。# 适用于 Python 3.8d.kind dogprint(d.kind) # dog —— 实例属性print(Dog.kind) # animal —— 类属性没变print(Animal.kind) # animal二、方法解析顺序MRO与 C3 线性化单继承时属性查找就是子类 → 父类 → 祖父类 → object很简单。一旦有多重继承顺序就不再直观。Python 用C3 线性化算法计算 MRO。官方文档把它描述为从左到右保持顺序、每个父类只调用一次、并且是单调的子类化不会打乱已有父类的优先级。这个顺序在类创建时就固定下来存在__mro__里。# 适用于 Python 3.8class A:passclass B(A):passclass C(A):passclass D(B, C):passprint([cls.__name__ for cls in D.__mro__])# [D, B, C, A, object]注意B在C前面——因为class D(B, C)里B写在左边C3 会保持这个从左到右的次序。规则是子类先于父类、声明靠左的先于靠右的。顺带纠正一个从老教程带过来的习惯Python 2 里必须写class C(object):才能得到新式类否则是旧式类、属性查找规则完全不同Python 2.7 已于 2020 年 1 月 1 日停止维护Python 3 里所有类都是新式类class C:与class C(object):等价括号里的object已属多余。三、super() 与协作式继承super()返回一个代理对象它把方法调用委托给 MRO 中当前类之后的下一个类——注意是MRO 里的下一个不是父类。文档里的例子说得很清楚如果__mro__是D - B - C - A - object而当type是B时super()会在C - A - object里搜索。这个细节是协作式多重继承的基础。看例子# 适用于 Python 3.8class Base:def process(self):return Baseclass LogMixin:def process(self):return Log- super().process()class CacheMixin:def process(self):return Cache- super().process()class Service(LogMixin, CacheMixin, Base):passprint([c.__name__ for c in Service.__mro__])# [Service, LogMixin, CacheMixin, Base, object]print(Service().process())# Log-Cache-BaseLogMixin.process里的super()并不是指向Base而是指向 MRO 中LogMixin之后的那一个也就是CacheMixin。这两个 mixin 谁也没硬编码对方super()会自动把链条串起来。只要每个参与者都调用super()链条就完整只要有一个环节忘了调后面的就全部被跳过。零参数super()有个限制它只能在类体内部定义的普通方法里用。文档特别提醒零参数形式在嵌套函数包括生成器表达式因为生成器表达式会隐式创建嵌套函数里不会按预期工作因为编译器需要靠紧邻的外层函数来确定self。四、继承还是组合继承表达的是is-a关系组合composition表达的是has-a。当两个类其实是包含而不是属于时硬套继承会得到可读性差的代码。# 适用于 Python 3.8# 不好Engine 不是 Car 的一种# class Car(Engine): ...# 好Car 有一个 Engineclass Engine:def start(self):return 引擎启动class Car:def __init__(self, engine):self.engine enginedef start(self):return 汽车 self.engine.start()常见坑点1. 子类定义__init__后忘了调super().__init__()❌# 适用于 Python 3.8class Child(Parent):def __init__(self, name, age):self.name name # 父类的初始化被完全跳过✅# 适用于 Python 3.8class Child(Parent):def __init__(self, name, age):super().__init__(name) # 先让父类把该做的做完self.age age2. 把可变对象写成类属性所有实例共享同一份❌# 适用于 Python 3.8class Team:members [] # 类属性所有实例共用def add(self, m):self.members.append(m)Team().add(a)之后另一个Team()的members里也有a。✅# 适用于 Python 3.8class Team:def __init__(self):self.members [] # 每个实例各有一份3. 多重继承里直接写Base.method(self)而不用super()❌ 硬编码某个基类绕过 MRO协作链断裂某个 mixin 被静默跳过。✅ 统一用super().method(...)让 MRO 决定顺序。4. 覆盖方法时改了调用签名❌ 父类def save(self, path)子类改成def save(self)多态调用一传参数就TypeError。✅ 覆盖方法保持向后兼容的签名新增参数一律给默认值。5. 以为双下划线属性是真私有❌ 子类里写self.__x以为访问不到父类的__x结果行为诡异。✅ Python 没有真正的私有__x会被名字改写name mangling成_ClassName__x。子类里同名属性其实改写成_Child__x两者是不同属性容易误解。6. 用super()却传错参数❌super(Child, self)在多重继承里写死成Child一旦实例是更靠下的子类搜索起点就错了。✅ 方法体内直接用零参数super()只有在类体外或需要精确控制时才用两参数形式。7. 类体里super()之外还残留isinstance判断来区分父类❌ 明明用了继承却仍在方法里if isinstance(self, Sub): ...两套分发机制打架。✅ 把差异交给方法覆盖需要协作的部分交给super()。8. 忘记object是所有类的最终基类❌ 认为A.__mro__只到A为止。✅ 每个类的 MRO 末尾都是object这也是为什么多重继承里object一定会出现且只出现一次。总结概念作用关键点class C(B)声明继承写入C.__bases__属性查找找属性/方法先实例__dict__再按 MRO 找类__mro__/mro()查看解析顺序C3 线性化类创建时固定super()调用 MRO 中的下一个类不是父类而是MRO 后继组合has-a 关系优先于继承降低耦合继承的价值在于复用和统一接口但它不是万能胶。判断该用继承还是组合时问一句子类是不是真的是父类的一种判断super()用得对不对时问一句我这条链条上每个人是不是都调了super()。把这两个问题答清楚大部分继承相关的怪问题都不会出现。
RELATED

相关推荐

Python+OpenCV车牌识别系统:两段式定位、分割与CNN识别

Python+OpenCV车牌识别系统:两段式定位、分割与CNN识别

简介:围绕Python与OpenCV实现车牌识别的毕业设计答辩PPT,面向计算机视觉入门者、本科毕业设计学生及希望梳理车牌识别流程的开发者,重点讲清车牌定位与字符识别两段式方案。内容从选题背景、我国车牌样式特点与技术难点切入,依次展…

📅 2026/10/30 2:54:50
C# 无需 IIS 搭建 Web 服务:.NET 8 自托管与 Kestrel 实战指南

C# 无需 IIS 搭建 Web 服务:.NET 8 自托管与 Kestrel 实战指南

简介:这份资源面向希望摆脱IIS依赖、快速搭建轻量级HTTP服务的C#开发者与学习者,聚焦用内置HttpListener实现自托管Web服务的完整示例。压缩包共17个文件、约18KB,以8个cs源码文件为核心,配合csproj项目配置、resx资源与xml配置&a…

📅 2026/10/30 2:49:50
Unity WebGL Dome全屏下中文输入稳定方案

Unity WebGL Dome全屏下中文输入稳定方案

简介:本资源是一个面向Unity WebGL开发者的中文输入功能完整实现Demo,专为解决Web端3D/2D应用中中文输入不兼容、输入法无法跟随光标、全屏模式下定位失效等典型痛点而设计,适用于中高级Unity开发者及跨平台WebGL项目工程师。压缩包共19个文件…

📅 2026/10/30 2:49:50
MORE NEWS

更多资讯

📰

EMC整改实战:辐射发射、传导发射与静电抗扰度排查思路

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

📰

嵌入式开发从裸机到Linux的四阶段工程路线图

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

📰

一周就业信息速递:从采集到发布的完整实操指南

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

📰

20+款ESP32在线开发工具盘点:浏览器仿真、烧录与免安装实战

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

📰

STM32实战进阶:用嵌入式C++补齐外设、总线与数据上云的关键技术解析

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

📰

ESP-IDF驱动DHT11实战:从时序原理到稳定采集的完整指南

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

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬