Python 继承、多态、封装、抽象
面向对象编程(OOP)是 Python 中的一种重要编程范式,它通过类和对象来组织代码。OOP 的四个核心概念是继承(Inheritance)、多态(Polymorphism)、封装(Encapsulation)和数据抽象(Data Abstraction)。下面将详细介绍这四个概念。
继承(Inheritance)
继承是面向对象编程(OOP)的一个基本概念,它允许一个类(子类或派生类)继承另一个类(基类或父类)的属性和方法。继承促进了代码的重用,并有助于在类之间建立层次结构。在 Python 中,可以通过继承现有的基类来创建新的派生类。
继承的类型
1. 单继承(Single Inheritance)
- 派生类从单个基类继承。
示例:
class Animal:def __init__(self, name):self.name = namedef speak(self):passclass Dog(Animal):def speak(self):return f"{self.name} says Woof!"dog = Dog("Buddy")
print(dog.speak()) # 输出: Buddy says Woof!
2. 多继承(Multiple Inheritance)
- 派生类从多个基类继承。
示例:
class Animal:def __init__(self, name):self.name = nameclass Canine:def bark(self):return "Woof!"class Dog(Animal, Canine):def speak(self):return f"{self.name} says {self.bark()}"dog = Dog("Buddy")
print(dog.speak()) # 输出: Buddy says Woof!
3. 多级继承(Multilevel Inheritance)
- 派生类从另一个派生类继承。
示例:
class Animal:def __init__(self, name):self.name = nameclass Mammal(Animal):def __init__(self, name, has_fur):super().__init__(name)self.has_fur = has_furclass Dog(Mammal):def speak(self):return f"{self.name} says Woof!"dog = Dog("Buddy", True)
print(dog.speak()) # 输出: Buddy says Woof!
4. 层次继承(Hierarchical Inheritance)
- 多个派生类从单个基类继承。
示例:
class Animal:def __init__(self, name):self.name = nameclass Dog(Animal):def speak(self):return f"{self.name} says Woof!"class Cat(Animal):def speak(self):return f"{self.name} says Meow!"dog = Dog("Buddy")
cat = Cat("Whiskers")
print(dog.speak()) # 输出: Buddy says Woof!
print(cat.speak()) # 输出: Whiskers says Meow!
5. 混合继承(Hybrid Inheritance)
- 两种或多种继承类型的组合。通常涉及层次继承、多级继承和多继承的混合。
示例:
class Animal:def __init__(self, name):self.name = nameclass Canine(Animal):def bark(self):return "Woof!"class Feline(Animal):def meow(self):return "Meow!"class Dog(Canine):def speak(self):return f"{self.name} says {self.bark()}"class Cat(Feline):def speak(self):return f"{self.name} says {self.meow()}"dog = Dog("Buddy")
cat = Cat("Whiskers")
print(dog.speak()) # 输出: Buddy says Woof!
print(cat.speak()) # 输出: Whiskers says Meow!
详细解释
-
单继承:
- 最简单的继承形式,派生类从单个基类继承。
- 适用于简单的类层次结构。
-
多继承:
- 派生类可以从多个基类继承。
- 适用于需要从多个来源继承功能的场景。
- 使用
super()
方法可以避免多重继承中的方法冲突。
-
多级继承:
- 派生类从另一个派生类继承,形成多级层次结构。
- 适用于需要逐步细化功能的场景。
-
层次继承:
- 多个派生类从单个基类继承。
- 适用于需要多个子类共享同一基类功能的场景。
-
混合继承:
- 两种或多种继承类型的组合。
- 适用于复杂的类层次结构,需要灵活地组合多种继承方式。
注意事项
-
方法解析顺序(MRO):
- 在多继承中,Python 使用 C3 线性化算法来确定方法解析顺序(MRO)。
- 可以使用
mro()
方法查看类的 MRO。 - 例如:
print(Dog.mro())
-
使用
super()
:super()
函数用于调用父类的方法,特别是在多继承中避免方法冲突。- 例如:
class Mammal(Animal):def __init__(self, name, has_fur):super().__init__(name)self.has_fur = has_fur
多态(Polymorphism)
多态是面向对象编程(OOP)的一个核心概念,它允许不同类的对象被视为单一超类的成员。多态通过单一接口表示多种底层形式(数据类型),使得不同类可以提供同名但根据对象类具有不同行为的方法。多态通过方法重载和方法重写实现,促进了代码的灵活性和集成,使得编写通用、可重用的代码变得更加容易。
多态的基本概念
-
方法重写(Method Overriding):
- 子类可以重写父类的方法,以提供不同的实现。
- 通过方法重写,可以在子类中扩展或修改父类的行为。
-
方法重载(Method Overloading):
- 同一个类中可以定义多个同名但参数不同的方法。
- Python 本身不直接支持方法重载,但可以通过默认参数和可变参数等技术实现类似的效果。
示例
以下是一个展示多态的 Python 示例:
class Animal:def speak(self):passclass Dog(Animal):def speak(self):return "Woof!"class Cat(Animal):def speak(self):return "Meow!"def make_animal_speak(animal):print(animal.speak())dog = Dog()
cat = Cat()make_animal_speak(dog) # 输出: Woof!
make_animal_speak(cat) # 输出: Meow!
封装(Encapsulation)
封装是面向对象编程(OOP)的一个核心概念,它将方法(函数)和数据(属性)组织成一个类单元。封装还防止未经授权访问对象的某些部分,从而保护数据不被误用和无意干扰。通常,这是通过使用前导下划线或双下划线将某些属性或方法设为私有来实现的。封装通过公共方法提供受控访问,鼓励模块化并帮助维护对象数据的完整性。
封装的基本概念
-
私有属性和方法:
- 使用单个前导下划线
_
表示“受保护”(protected)属性或方法,通常不应在类外部直接访问。 - 使用双前导下划线
__
表示“私有”(private)属性或方法,Python 会对其进行名称改写(name mangling),使其更难以在类外部访问。
- 使用单个前导下划线
-
公共方法:
- 提供公共方法来访问和修改私有属性,确保数据的完整性和安全性。
示例
以下是一个展示 Python 封装的示例:
class BankAccount:def __init__(self, owner, balance):self.owner = ownerself.__balance = balance # 私有属性def deposit(self, amount):if amount > 0:self.__balance += amountprint(f"Deposited {amount}. New balance: {self.__balance}")else:print("Deposit amount must be positive.")def withdraw(self, amount):if 0 < amount <= self.__balance:self.__balance -= amountprint(f"Withdrew {amount}. New balance: {self.__balance}")else:print("Invalid withdrawal amount.")def get_balance(self):return self.__balance# 创建 BankAccount 类的对象
account = BankAccount("Alice", 1000)# 调用公共方法
account.deposit(500) # 输出: Deposited 500. New balance: 1500
account.withdraw(200) # 输出: Withdrew 200. New balance: 1300# 尝试直接访问私有属性(不推荐)
# print(account.__balance) # 这将引发 AttributeError# 通过公共方法访问私有属性
print(account.get_balance()) # 输出: 1300
数据抽象(Data Abstraction)
数据抽象是面向对象编程(OOP)的一个重要原则,其目的是隐藏系统的复杂实现细节,只向用户展示必要和相关的信息。数据抽象通过提供简单和直观的接口,有助于提高效率和减少复杂性。它使程序员能够处理简化的系统表示,并管理复杂的操作。在 Python 中,可以使用抽象基类(Abstract Base Classes, ABC)和接口来实现数据抽象。
抽象基类(Abstract Base Classes, ABC)
抽象基类是定义了一组抽象方法的类,这些方法必须由派生类实现。抽象方法是没有具体实现的方法,只有方法签名。通过使用抽象基类,可以确保所有派生类都实现特定的方法,从而保证标准化和一致的交互。
示例
以下是一个使用抽象基类实现数据抽象的 Python 示例:
from abc import ABC, abstractmethodclass Shape(ABC):@abstractmethoddef area(self):pass@abstractmethoddef perimeter(self):passclass Rectangle(Shape):def __init__(self, width, height):self.width = widthself.height = heightdef area(self):return self.width * self.heightdef perimeter(self):return 2 * (self.width + self.height)class Circle(Shape):def __init__(self, radius):self.radius = radiusdef area(self):return 3.14 * self.radius ** 2def perimeter(self):return 2 * 3.14 * self.radius# 创建 Rectangle 和 Circle 对象
rect = Rectangle(10, 20)
circ = Circle(15)# 访问 area 和 perimeter 方法
print(f"Rectangle Area: {rect.area()}") # 输出: Rectangle Area: 200
print(f"Rectangle Perimeter: {rect.perimeter()}") # 输出: Rectangle Perimeter: 60
print(f"Circle Area: {circ.area()}") # 输出: Circle Area: 706.5
print(f"Circle Perimeter: {circ.perimeter()}") # 输出: Circle Perimeter: 94.2
详细解释
-
定义抽象基类
Shape
:Shape
类继承自ABC
类,并定义了两个抽象方法area
和perimeter
。- 抽象方法使用
@abstractmethod
装饰器声明,表示这些方法必须在派生类中实现。
-
定义具体类
Rectangle
和Circle
:Rectangle
类继承自Shape
类,并实现了area
和perimeter
方法。Circle
类继承自Shape
类,并实现了area
和perimeter
方法。
-
创建对象并调用方法:
- 创建
Rectangle
和Circle
对象。 - 调用
area
和perimeter
方法,计算并输出矩形和圆形的面积和周长。
- 创建
数据抽象的好处
-
隐藏复杂性:
- 通过抽象基类,可以隐藏具体的实现细节,只向用户提供必要的接口。
- 例如,用户不必了解如何计算矩形和圆形的面积和周长,只需调用相应的方法即可。
-
标准化接口:
- 抽象基类确保所有派生类都实现特定的方法,从而提供标准化的接口。
- 例如,所有形状类都必须实现
area
和perimeter
方法,这使得处理不同形状的代码更加一致和简洁。
-
提高可维护性:
- 通过数据抽象,代码更加模块化,易于维护和扩展。
- 例如,如果需要添加新的形状类(如
Triangle
),只需实现area
和perimeter
方法,而无需修改现有代码。
-
简化交互:
- 用户可以使用相同的接口与不同类型的对象进行交互,而不必了解每个对象的具体实现。
- 例如,可以编写一个通用函数来处理任何
Shape
对象,而无需关心它是Rectangle
还是Circle
。
总结
面向对象编程的核心概念:
- 继承(Inheritance):允许一个类(子类)继承另一个类(父类)的属性和方法。
- 多态(Polymorphism):允许不同类的对象被视为单一超类的成员,通过方法重写和重载实现。
- 封装(Encapsulation):将数据和操作数据的方法绑定在一起,通过私有属性和公共方法保护数据。
- 数据抽象(Data Abstraction):隐藏系统的复杂实现细节,只向用户展示必要和相关的信息,通过抽象基类和接口实现。
相关文章:

Python 继承、多态、封装、抽象
面向对象编程(OOP)是 Python 中的一种重要编程范式,它通过类和对象来组织代码。OOP 的四个核心概念是继承(Inheritance)、多态(Polymorphism)、封装(Encapsulation)和数据…...

在.net下后台设置前台UEditor编辑器不可编辑
今天手下有个问:当用户填写提交后,再次显示提交页面时,该页面的UEditor编辑器需要设置成不可编辑,怎么实现? 可以用后台调用前台js的方式实现: 例如: 前台页面: <div style&qu…...

Flutter CustomScrollView 效果-顶栏透明与标签栏吸顶
CustomScrollView 效果 1. 关键组件 CustomScrollView, SliverOverlapAbsorber, SliverPersistentHeader 2. 关键内容 TLDR SliverOverlapAbsorber 包住 pinned为 true 的组件 可以被CustomScrollView 忽略高度。 以下的全部内容的都为了阐述上面这句话。初阶 Flutter 开发知…...

【新手入门软件测试--该如何分辨前后端问题及如何定位日志--前后端问题分辨与日志定位查询问题】
前后端问题分辨与日志定位查询 一、前端问题1. 页面无法加载2. 样式错乱3. API请求失败4. 数据格式错误5. 跨域请求问题 二、后端问题6. 表单验证失败7. 数据库连接失败8. 请求超时9. 权限问题10. JavaScript运行错误 三、日志查询的方法1. 查看日志文件2. 过滤关键字3. 实时查…...

【Java Web】DAO模式及单例模式(含代码示例)
文章目录 JDBC封装DAO模式实体类DAO接口DAO实现类数据源配置基础DAO类业务逻辑层 单例模式饿汉式懒汉式 JDBC封装 JDBC(Java Database Connectivity)封装是一种将 JDBC 的基本操作和常见的数据库访问逻辑封装成易于使用的工具类或框架的方法。这样做的目…...

深入探讨SEO分析技巧助力网站流量提升
内容概要 在当前的数字化时代,SEO分析的重要性不言而喻。它是提升网站流量的关键工具,帮助站长有效地优化网站内容和结构。通过系统的SEO分析,站长可以掌握用户搜索行为和需求,从而制定出更具针对性的内容策略。例如,…...

Chrome 130 版本开发者工具(DevTools)更新内容
Chrome 130 版本开发者工具(DevTools)更新内容 一、网络(Network)面板更新 1. 重新定义网络过滤器 网络面板获新增了一些过滤条件,这些过滤条件是根据反馈重新设计的,特定于类型的过滤条件保持不变&…...

深度学习基础知识-残差网络ResNet
目录 一、ResNet 的核心思想:残差学习(Residual Learning) 二、ResNet 的基本原理 三、ResNet 网络结构 1. 残差块(Residual Block) ResNet 的跳跃连接类型 2. 网络结构图示 四、ResNet 的特点和优势 五、ResNe…...

Linux云计算个人学习总结(二)
高级文件系统 一、RSYNC概述 1、作用:快速的文件复制工具(支持本地和远程),以及删除、查看等基本功能。 2、特点:支持实时(inotify、sersync)的增量备份工具3、模式:检查模式&#…...

Java入门(7)--网络编程
Java网络编程:构建网络应用的基石 🌐 🎯 掌握Java网络编程,打造强大的网络应用! 在上一篇文章中,我们探讨了Java的I/O操作和反射机制。今天,让我们深入学习Java网络编程,了解如何构建…...

[思考记录]思维局限,以为懂了
最近配合整理一些内容,找到较早期的某些产品设计资料在翻阅回顾。在这次回顾过程中,发现当时自己的理解存在很多局限。 以资源体系的设计为例,那时自认为已经“懂了”,对相关的概念、作用关系、组成及实现等都有一定的了解&#x…...

力扣题目解析--最长公共前缀
题目 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 ""。 示例 1: 输入:strs ["flower","flow","flight"] 输出:"fl"示例 2ÿ…...

不画饼——研究生学习和赚钱的平衡点
在现代社会中,年轻人面临着学习和赚钱之间的矛盾。尤其是在经济压力日益增大的背景下,如何在这两者之间找到合适的平衡点,成为了许多学生和职场新人面临的重要问题。本文将探讨在何种情况下应该听从老师的建议,专注于学习…...

华为实时视频使用FLV播放RTSP流
import flvjs from ‘flv.js’; 安装flv <video style"width:100%;height:100%;" ref"videoHWRef" ></video>// src 华为rtsp流 rtsp://admin:Huaweivideo10.10.8.151:554/xxx/trackID1// url 需要后端提供视频源地址playVideo() {if (fl…...

JAVA设计模式之【建造者模式】
1 定义 建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 2 类图 产品类(Product):表示被创建的复杂…...

【jvm】为什么Xms和Xmx的值通常设置为相同的?
目录 1. 说明2. 避免性能开销3. 提升稳定性4. 简化配置5. 优化垃圾收集6. 获取参数6.1 代码示例6.2 结果示例 1. 说明 1.-Xms 和 -Xmx 参数分别用于设置堆内存的初始大小(最小值)和最大大小。2.在开发环境中,开发人员可能希望快速启动应用程…...

windows查看net网络监听端口命令和工具(ipconfig、netstat、tasklist、TCPView)
文章目录 使用命令提示符(CMD)查看网络连接和配置使用 netstat 命令查看监听端口查看特定的端口查看TCP监听端口tasklist查看对应进程ID的程序Get-NetTCPConnection 命令使用 TCPView工具使用命令提示符(CMD) 查看网络连接和配置 ipconfig :显示所有网络 适配器的当前 TC…...

JAVA-数据结构- 二叉搜索树
1.搜索树 前面我们已经使用C语言学习完了二叉树,懂得了一些二叉树的基本性质已经实现方法 https://mp.csdn.net/mp_blog/creation/editor/139572374,本文我们来一起进行二叉树的衍生-二叉搜索树 1.1 概念 二叉搜索树又称二叉排序树,它或者是…...

深入研究 RAG 流程中的关键组件
我们已经看到了整个RAG流程,并获得了第一手的实践经验,您可能会对RAG流程中一些组件的使用和目的存在很多疑惑,比如RunnablePassthrough。在本节中,我们将进一步了解这些关键组件。 RAG的核心模型思想是将一个复杂的任务分解为多…...

新手如何学习python并快速成为高手
英雄Python入门到精通链接:https://pan.quark.cn/s/57162ec366a9 学习Python作为新手,有以下几个步骤: 学习基本概念和语法:首先,你需要学习Python的基本概念和语法。可以通过在线教程、书籍或者视频教程来学习。了解…...

Linux历史命令history增加执行时间显示
Centos系统默认历史命令显示如下 为了更好的溯源,获取执行命令的准确时间,需要增加一些配置 设置环境变量 vim /etc/profile 在最下面添加以下环境配置 export HISTTIMEFORMAT"%Y-%m-%d %H:%M:%S " 立即刷新该环境变量 source /etc/pro…...

从 vue 源码看问题 — 你知道 Hook Event 吗?
前言 在之前的几篇文章中,都有提到 vue 中调用生命周期钩子时是通过 callHook() 方法进行调用的,比如在初始化篇章中调用 beforeCreate 和 created 生命周期钩子方式如下: 那么接下来一起来了解下到底什么是 Hook Event ? Hook Event 是什…...

信息安全工程师(68)可信计算技术与应用
前言 可信计算技术是一种计算机安全体系结构,旨在提高计算机系统在面临各种攻击和威胁时的安全性和保密性。 一、可信计算技术的定义与原理 可信计算技术通过包括硬件加密、受限访问以及计算机系统本身的完整性验证等技术手段,确保计算机系统在各种攻击和…...

每日OJ题_牛客_相差不超过k的最多数_滑动窗口_C++_Java
目录 牛客_相差不超过k的最多数_滑动窗口 题目解析 C代码 Java代码 牛客_相差不超过k的最多数_滑动窗口 相差不超过k的最多数_牛客题霸_牛客网 (nowcoder.com) 描述: 给定一个数组,选择一些数,要求选择的数中任意两数差的绝对值不超过 …...

来咯来咯webSocket
在项目总目录下 设置socketServe文件夹 里面创建下面两个文件 使用的时候需要开启 node webSocket.cjs var { Server } require(ws); var moment require(moment);const wss new Server({port: 8888 });let id 0; let onlineMemberList []; const defaultUser user;wss…...

Android CALL关于电话音频和紧急电话设置和获取
获取音频服务,设置音源类型:电话类型和获取最大电话音量,响铃模式 private AudioManager mAudioManager; mAudioManager (AudioManager) getSystemService(AUDIO_SERVICE); mAudioManager.setStreamVolume(AudioManager.STREAM_VOIC…...

【春秋云镜】CVE-2023-23752
目录 CVE-2023-23752漏洞细节漏洞利用示例修复建议 春秋云镜:解法一:解法二: CVE-2023-23752 是一个影响 Joomla CMS 的未授权路径遍历漏洞。该漏洞出现在 Joomla 4.0.0 至 4.2.7 版本中,允许未经认证的远程攻击者通过特定 API 端…...

C#-__DynamicallyInvokable
[__DynamicallyInvokable] 属性是用于 .NET Framework 中的特性之一。这个特性通常用于标记在动态语言运行时中可以进行调用的方法或属性。 当一个方法或属性被标记为 [__DynamicallyInvokable],它表明这个成员在动态语言的环境中是可调用的。换句话说,…...

2024年最新10款顶级项目管理软件排行
项目管理软件在现代项目管理中扮演着至关重要的角色,它不仅仅是一个工具,更是一种高效、系统化的方法来管理和优化项目流程,帮助项目经理和团队成员快速了解项目状态,加速项目进展。 进度猫 进度猫是一款以甘特图为向导的轻量级…...

Python NLTK进阶:深入自然语言处理
目录 Python NLTK进阶:深入自然语言处理 1. 文本处理技术 1.1 命名实体识别(NER) 1.2 共指消解 2. 语义分析 2.1 语义角色标注(SRL) 2.2 词义消歧(Word Sense Disambiguation) 3. 机器学…...