Python 类的继承基础讲解

舞夢輝影

舞夢輝影

2025-09-21

1041人浏览

原创

继承实现代码复用与“is-a”关系,如dog和cat继承animal共享属性方法;多重继承需谨慎使用,易引发mro复杂性;优先选择组合表达“has-a”关系以提升灵活性。

python 类的继承基础讲解

Python的类继承,简单来说,就是让一个新类(我们叫它子类或派生类)能够“学到”另一个已有的类(父类或基类)的各种能力和特性。这就像是生物学上的遗传,子代继承了父代的基因,但也可以在此基础上发展出自己的独特之处。核心目的就是代码复用,避免写重复的代码,同时也能更好地组织和管理代码结构,让它们之间存在一种“是”的关系,比如“狗是一种动物”。

在Python里,实现继承其实非常直接。当你定义一个类时,可以在类名后面括号里指定它要继承的父类。

class Animal:
    def __init__(self, name):
        self.name = name
        print(f"{self.name} 出生了。")

    def speak(self):
        raise NotImplementedError("子类必须实现这个方法")

    def move(self):
        print(f"{self.name} 正在移动。")

class Dog(Animal): # Dog 继承自 Animal
    def __init__(self, name, breed):
        super().__init__(name) # 调用父类的构造方法
        self.breed = breed
        print(f"这是一只 {self.breed} 的狗。")

    def speak(self): # 重写父类的 speak 方法
        return "汪汪!"

class Cat(Animal): # Cat 也继承自 Animal
    def __init__(self, name):
        super().__init__(name)
        print(f"这是一只猫。")

    def speak(self):
        return "喵喵!"

# 实例化
my_dog = Dog("旺财", "金毛")
print(f"{my_dog.name} 说:{my_dog.speak()}")
my_dog.move()

my_cat = Cat("咪咪")
print(f"{my_cat.name} 说:{my_cat.speak()}")
my_cat.move()

从上面这个例子能看出来,

Dog
Cat
都继承了
Animal
类的
name
属性和
move
方法。同时,它们也都有各自独特的属性(
Dog
breed
)和行为(各自实现了
speak
方法)。这里
super().__init__(name)
是个关键,它负责调用父类
Animal
的构造方法,确保
Animal
类的初始化逻辑也被执行。如果没有这行,
Dog
Cat
就不会拥有
name
属性,或者说,
Animal
类中定义的初始化逻辑就不会被触发。我个人在刚接触这块儿的时候,就经常忘记调用
super()
,然后发现一些属性没初始化,搞得一头雾水。

Python继承机制到底能解决哪些实际问题?

继承最直观的用处,就是代码复用。想想看,如果

Animal
有十几个通用的方法,比如
eat()
sleep()
breathe()
,如果不用继承,每个子类(
Dog
Cat
Bird
)都得重新写一遍这些方法,那代码量得多大,维护起来得多麻烦?有了继承,这些通用行为只需要在父类定义一次,子类就能直接用。这大大减少了冗余,也让代码更简洁。

再一个就是建立清晰的逻辑关系。继承表达的是一种“is-a”关系。比如“狗是一种动物”,“轿车是一种交通工具”。这种关系在建模现实世界时非常有用,它让你的程序结构更符合人类的认知,也更容易理解。当你想扩展功能时,比如要添加一个新的动物类型,你只需要创建一个新的子类继承

Animal
,然后实现它特有的部分就行,不需要从头开始写所有通用的东西。这让系统的可扩展性变得非常好。

此外,继承也为多态性打下了基础。虽然这听起来有点高级,但简单来说,就是不同的子类可以对同一个父类方法有不同的实现。比如上面的

speak()
方法,
Dog
Cat
都有,但它们说出来的话不一样。这样,你就可以写一个函数,它接受一个
Animal
对象作为参数,然后调用
animal.speak()
,具体发出什么声音,取决于传入的是
Dog
还是
Cat
对象。这让代码变得非常灵活,能够处理不同类型的对象,而无需关心它们的具体类型。

在Python中,多重继承是不是一个好主意?

Python是支持多重继承的,这意味着一个子类可以同时继承多个父类。这听起来功能很强大,但实际用起来,我个人觉得它是一把双刃剑,得小心翼翼地用。

ApiPost接口调试与文档生成工具
ApiPost接口调试与文档生成工具

ApiPost是一个支持团队协作,支持模拟POST、GET、PUT等常见请求,并可直接生成文档的API调试、管理工具,ApiPost是后台接口开发者或前端、接口测试人员的工作必备工具。快速生成、一键导出API文档。感兴趣的朋友快来下载吧。软件说明ApiPost官方版是一款十分出色的接口调试与文档生成工具,ApiPost官方版界面美观大方,功能强劲实用,支持团队协作,支持模拟POST、GET、PUT等常见请求,是后台接口开发者或前端、接口测试人员的工作必备工具。软件特色更方便支持接口调试的同时快速生成、一键

下载

多重继承的主要问题在于复杂性方法解析顺序(MRO)。当一个子类继承了多个父类,并且这些父类中存在同名的方法时,Python就需要一个规则来决定到底调用哪个父类的方法。这个规则就是MRO。Python采用C3线性化算法来确定MRO,虽然它很智能,但对于开发者来说,理解和预测MRO的行为有时候会非常烧脑,尤其是在继承链很深或者结构复杂的时候。这也就是所谓的“菱形继承问题”(Diamond Problem)的根源之一。

class A:
    def method(self):
        print("Method from A")

class B(A):
    def method(self):
        print("Method from B")

class C(A):
    def method(self):
        print("Method from C")

class D(B, C): # 多重继承
    pass

d = D()
d.method() # 到底会打印哪个?
print(D.__mro__) # 查看MRO

运行上面这段代码,你会发现它打印的是 "Method from B"。通过

D.__mro__
可以看到
D
的方法解析顺序是
(<class>, <class>, <class>, <class>, <class>)</class></class></class></class></class>
。Python会按照这个顺序查找方法,找到第一个就停下。

所以,我的建议是:尽量避免滥用多重继承。在大多数情况下,你可以通过组合(Composition)或者使用Mixin(混入)类来达到类似的目的,而且代码会更清晰、更易于维护。Mixin是一种特殊的多重继承用法,它通常不带有自己的状态,只提供一些特定的功能方法,像“插件”一样被混入到其他类中。这种方式能有效减少多重继承带来的复杂性。

什么时候应该用继承,什么时候该用组合?

这是一个软件设计中非常经典且重要的问题。简单来说,它们表达了两种不同的关系:

继承(Inheritance):表达“is-a”关系。 当一个对象“是”另一个对象的一种特殊类型时,就应该考虑使用继承。

  • 例子:
    Dog
    is a
    Animal
    Car
    is a
    Vehicle
  • 优点: 代码复用,建立层次结构,支持多态。
  • 适用场景: 当你有一个明确的父子关系,子类是对父类的具体化或扩展,并且子类共享父类的核心行为和属性。

组合(Composition):表达“has-a”关系。 当一个对象“拥有”另一个对象作为其一部分时,就应该考虑使用组合。

  • 例子:
    Car
    has an
    Engine
    Computer
    has a
    CPU
  • 优点: 灵活性高,降低耦合度。一个对象可以通过组合不同的组件来获得不同的行为,而不需要复杂的继承链。
  • 适用场景: 当你希望一个类能够复用其他类的功能,但它们之间没有明确的“is-a”关系时。或者当你希望在运行时能够动态地改变一个对象的行为时。
# 组合的例子
class Engine:
    def start(self):
        return "Engine started!"

class Car:
    def __init__(self):
        self.engine = Engine() # Car 拥有一个 Engine 对象

    def drive(self):
        print(self.engine.start())
        print("Car is driving.")

my_car = Car()
my_car.drive()

在这个

Car
Engine
的例子中,
Car
并没有继承
Engine
,而是将
Engine
作为自己的一个成员变量。
Car
拥有一个
Engine
。这样设计的好处是,如果将来我想把
Engine
换成
ElectricMotor
,我只需要修改
Car
的构造函数或者提供一个方法来替换
Engine
实例,而不需要改变
Car
的继承结构。这比继承更灵活,也更符合“优先使用组合而非继承”的设计原则。

总的来说,如果你在纠结用继承还是组合,我的经验是:优先考虑组合。只有当你确定两个类之间存在强烈的“is-a”关系,并且继承能带来显著的复用和多态优势时,再选择继承。组合通常能带来更松散的耦合和更高的灵活性,这对于长期维护和扩展代码来说非常重要。

Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!

相关专题

更多
java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

2025.11.27

187

14

class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

2024.01.03

1745

7

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

2025.12.06

182

9

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

2023.08.14

2443

4

墨刀AI提示词教学
墨刀AI提示词教学

本合集由PHP中文网精心整理,为您提供全面的墨刀AI提示词教学。内容涵盖高质量原型撰写公式与实操窍门,助您轻松掌握AI设计工具。无论是零基础入门还是进阶技巧,都能让您快速上手,大幅提升产品设计与协作效率。

2026.08.04

10

21

墨刀AI完整入门
墨刀AI完整入门

PHP中文网为您倾力打造墨刀AI保姆级入门指南完整版!本合集从零基础讲起,涵盖AI生成原型、提示词优化、图片转原型及多轮对话等核心功能。无论您是新手还是进阶用户,都能轻松掌握产品设计全流程。快来PHP中文网,一键解锁高效设计技巧,让想法即刻成型!

2026.08.04

8

20

墨刀AI进阶技巧
墨刀AI进阶技巧

本合集由PHP中文网精心整理,为您提供墨刀AI核心进阶策略指南。内容涵盖高效提示词写作、原型智能生成与微调、结构化导图制作及行业分析报告输出等实战技巧。助您轻松掌握AI设计工具,大幅提升产品设计与团队协作效率。

2026.08.04

10

14

火山引擎实名认证失败怎么办
火山引擎实名认证失败怎么办

火山引擎实名认证失败可能与证件信息填写错误、姓名或企业信息不一致、证件照片不清晰、营业执照状态异常、手机号验证失败或审核资料不完整有关。本专题整理个人认证、企业认证、资料上传、审核退回、重新提交和认证不通过的常见处理方法。

2026.08.04

5

10

火山引擎域名备案流程详解
火山引擎域名备案流程详解

火山引擎域名备案适合需要在火山引擎云服务器、对象存储、CDN或网站服务上绑定域名的用户参考。本专题整理备案入口、账号实名认证、备案类型选择、主体信息填写、网站信息提交、资料上传、初审核验、管局审核和备案失败排查,帮助用户完成网站上线前的备案流程。

2026.08.04

1

10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go语言教程-全程干货无废话
Go语言教程-全程干货无废话

共100课时 | 16万人学习

JavaScript设计模式完整视频教程
JavaScript设计模式完整视频教程

共60课时 | 14.2万人学习

Python进阶视频教程
Python进阶视频教程

共30课时 | 8.7万人学习