当前位置: 首页 > news >正文

Python 继承和多态

Python 里的继承和多态是面向对象编程(OOP)的核心概念,学好了能让你的代码更灵活、可复用,还能少写不少重复代码。

参考文章:Python 继承和多态 | 简单一点学习 easyeasy.me

1. 什么是继承?

继承的基本概念

继承就是让一个类(子类)“继承”另一个类(父类)的属性和方法。子类可以直接用父类的功能,还能根据需要扩展或修改。打个比方,父类就像是“模板”,子类是基于模板再加工的“定制版”。

为什么需要继承

  • 代码复用:不用重复写相同的代码,父类的功能直接拿来用。
  • 逻辑清晰:把通用的功能放父类,子类只管自己的“个性”部分。
  • 扩展性强:子类可以加新功能,也可以改父类的行为。

Python 中类的基本定义回顾

在 Python 里,类用 class 关键字定义,属性是类的“变量”,方法是类的“函数”。来看个简单例子:

class Animal:def __init__(self, name):self.name = namedef speak(self):return f"{self.name} 发出声音"# 创建一个实例
dog = Animal("小狗")
print(dog.speak())  # 输出:小狗 发出声音

2. 单继承的实现

定义父类和子类

Python 的继承很简单,子类在定义时括号里写上父类的名字。子类会自动拥有父类的属性和方法。

class Animal:  # 父类def __init__(self, name):self.name = namedef speak(self):return f"{self.name} 发出声音"class Dog(Animal):  # 子类,继承 Animalpass# 测试
dog = Dog("旺财")
print(dog.speak())  # 输出:旺财 发出声音

Dog 啥也没干,但因为继承了 Animal,它直接能用 speak 方法。

子类如何调用父类的方法和属性

子类可以用 super() 来调用父类的 __init__ 或其他方法,方便在子类里扩展父类的功能。

class Dog(Animal):def __init__(self, name, breed):super().__init__(name)  # 调用父类的 __init__self.breed = breed  # 子类新增属性def speak(self):  # 重写父类方法return f"{self.name} 汪汪叫"# 测试
dog = Dog("旺财", "哈士奇")
print(dog.speak())  # 输出:旺财 汪汪叫
print(dog.breed)    # 输出:哈士奇

方法重写(Override)

子类可以“重写”父类的方法,改成自己的逻辑。像上面例子,Dog 重写了 speak,让它输出“汪汪叫”而不是“发出声音”。


3. 多继承和 MRO

什么是多继承

Python 允许一个类同时继承多个父类,这叫多继承。听起来很酷,但用不好容易把代码搞乱。来看例子:

class Flyer:def fly(self):return "我在飞!"class Swimmer:def swim(self):return "我在游!"class Duck(Animal, Flyer, Swimmer):  # 鸭子继承了三个类def __init__(self, name):super().__init__(name)# 测试
duck = Duck("唐老鸭")
print(duck.speak())  # 输出:唐老鸭 发出声音
print(duck.fly())    # 输出:我在飞!
print(duck.swim())   # 输出:我在游!

Duck 继承了 AnimalFlyerSwimmer,所以它会叫、会飞、会游。

Python 的方法解析顺序(MRO)

多继承时,如果多个父类有同名方法,Python 得决定用哪个。这靠 MRO(Method Resolution Order) 来搞定。MRO 决定了方法查找的顺序,用的是 C3 线性化算法。

你可以用 类名.__mro__ 看 MRO 顺序:

print(Duck.__mro__)
# 输出:
# (<class '__main__.Duck'>, <class '__main__.Animal'>, <class '__main__.Flyer'>, 
#  <class '__main__.Swimmer'>, <class 'object'>)

Python 会按这个顺序找方法,super() 也会按这个顺序调用父类方法。

多继承的注意事项

  • 避免复杂继承:多继承容易让代码逻辑混乱,能用单继承就别用多继承。
  • 小心同名方法:如果多个父类有同名方法,确保 MRO 顺序是你想要的。
  • 用 super() 谨慎:多继承下,super() 的行为可能不符合直觉,建议明确调用父类方法。

4. 多态的概念和实现

什么是多态

多态就是“一种接口,多种实现”。简单说,不同的类可以用同样的方法名,但行为各不相同。多态让代码更灵活,调用方不用管具体是哪个类,只要方法名对就行。

Python 中多态的实现方式

Python 是动态语言,天然支持多态,不需要像 Java 那样的接口或抽象类。只需要不同类有同名方法,就能实现多态。

class Cat(Animal):def speak(self):return f"{self.name} 喵喵叫"class Cow(Animal):def speak(self):return f"{self.name} 哞哞叫"# 多态测试
animals = [Dog("旺财", "哈士奇"), Cat("咪咪"), Cow("大黄")]
for animal in animals:print(animal.speak())

输出:

旺财 汪汪叫
咪咪 喵喵叫
大黄 哞哞叫

这里 DogCatCow 都继承了 Animal,但 speak 方法各有不同。调用时只管 speak(),不用管具体是哪种动物,这就是多态。

多态的实际例子

假设我们要写一个“动物表演”程序,动物种类可能随时加新种类。多态可以让我们轻松扩展:

def animal_show(animal):print(f"表演开始:{animal.speak()}")# 测试
animal_show(Dog("旺财", "哈士奇"))  # 输出:表演开始:旺财 汪汪叫
animal_show(Cat("咪咪"))            # 输出:表演开始:咪咪 喵喵叫

animal_show 函数只关心 animal 有没有 speak 方法,完全不care具体是什么类。


5. 继承和多态的实际应用

什么时候用继承和多态

  • 继承:当你有一堆类有共同的属性或方法时,抽个父类出来,把共性放进去。比如,DogCat 都有 namespeak,就适合用继承。
  • 多态:当你希望用统一的接口处理不同类型的对象时,用多态。比如,前面例子里的 animal_show 函数,能处理任何有 speak 方法的对象。

常见的设计模式场景

  • 工厂模式:用一个工厂类根据输入创建不同子类的对象,调用时只用统一接口。
  • 策略模式:通过多态实现不同策略,比如不同动物的叫声。
  • 模板方法:父类定义流程,子类实现具体步骤。

例子(模板方法):

class Game:def play(self):self.start()self.play_round()self.end()def start(self):print("游戏开始")def play_round(self):pass  # 子类实现def end(self):print("游戏结束")class Chess(Game):def play_round(self):print("下棋中...")class CardGame(Game):def play_round(self):print("打牌中...")# 测试
chess = Chess()
chess.play()
# 输出:
# 游戏开始
# 下棋中...
# 游戏结束

注意事项和陷阱

  • 不要滥用继承:继承层级太深会让代码难维护,优先考虑组合(has-a 关系)而不是继承(is-a 关系)。
  • 多态要简单:方法名一致不代表逻辑一致,确保多态的接口语义清晰。
  • 小心 super():尤其在多继承时,super() 可能调用到意外的父类。
  • 性能考虑:继承和多态虽然方便,但深层继承链可能影响性能,特别是在大项目里。
http://www.dtcms.com/a/322920.html

相关文章:

  • ElaWidgetTools qt5+vs2019编译
  • 1.JavaScript 介绍
  • 基于STM32的智能电表设计与实现
  • 计算机组成原理2-4-1:浮点数的表示
  • Linux 安装 JDK 8u291 教程(jdk-8u291-linux-x64.tar.gz 解压配置详细步骤)​
  • 【c++】探秘Loop机制:C++中优雅的双向数据交互模式
  • 低速CAN 高速CAN是否兼容?
  • 功能测试详解
  • 【面试题】cookie和session 的区别
  • Ubuntu下Nginx的部署后端项目(Java为例),配置Nginx代理
  • 自编教材实操课程学习笔记
  • 商品、股指及ETF期权五档盘口Tick级与分钟级历史行情数据多维解析
  • dify离线插件安装
  • Spring Boot Starter 自动化配置原理深度剖析
  • 【工具变量】地市人力资本水平数据集(2003-2023年)
  • 聊聊经常用的微服务
  • Java 枚举解析:从基础到进阶的知识点与注意事项
  • 【完整源码+数据集+部署教程】植物生长阶段检测系统源码和数据集:改进yolo11-rmt
  • gRPC for C++ 实战全流程 —— 从零搭建到同步/异步服务
  • vw和vh:CSS中的视口相对单位
  • Linux下管道的实现
  • 第十四节 代理模式
  • Android 设置/修改系统NTP服务地址
  • 2010-2024 地级市、上市公司“信息惠民国家试点城市”DID
  • Jenkins全链路教程——条件判断与流程控制
  • 从夯到拉,锐评MC所有武器
  • RK3568笔记九十九:基于FFMPEG拉取RTSP流MPP硬解码视频显示
  • 第5章 Excel公式与函数应用指南(2):数学函数
  • 【C语言】深入探索预处理
  • 系统蓝屏,黑屏,花屏,绿屏,白屏等问题统一解决软件,驱动人生下载