Day 15:【99天精通Python】面向对象编程(OOP)中篇 - 封装、继承与多态

Day 15:【99天精通Python】面向对象编程(OOP)中篇 - 封装、继承与多态

前言

欢迎来到第15天!

在昨天的课程中,我们学会了如何定义类和创建对象。但这只是 OOP 的冰山一角。面向对象编程之所以强大,归功于它的三大核心特性:封装 (Encapsulation)继承 (Inheritance)多态 (Polymorphism)

这三个词听起来很高大上,但实际上它们是为了解决我们在编程中遇到的实际问题:

  • 封装:为了保护数据,不让别人随意修改。
  • 继承:为了偷懒(复用代码),爸爸有的儿子不用再写一遍。
  • 多态:为了灵活,同一个指令让不同的对象做不同的事。

本节内容:

  • 私有属性与封装
  • 继承的基本语法
  • 方法重写 (Overriding)
  • super()函数
  • 多态与鸭子类型
  • 实战练习

一、封装 (Encapsulation):保护你的数据

1.1 公有 vs 私有

默认情况下,Python 类中的属性都是公有 (Public)的,在类的外部可以随意访问和修改。这有时候很不安全。

classAccount:def__init__(self,balance):self.balance=balance acc=Account(100)acc.balance=-999999# 外部可以直接修改,这太危险了!

为了保护数据,我们可以将属性定义为私有 (Private)。在 Python 中,只需要在属性名前加两个下划线__

1.2 私有属性的使用

classAccount:def__init__(self,balance):self.__balance=balance# 私有属性defget_balance(self):"""提供公开的方法获取余额"""returnself.__balancedefdeposit(self,amount):"""提供公开的方法修改余额,可以在这里加逻辑判断"""ifamount>0:self.__balance+=amountelse:print("金额无效")acc=Account(1000)# print(acc.__balance) # 报错!外部无法访问print(acc.get_balance())# 1000 (通过方法访问)acc.deposit(500)

原理:Python 实际上是将__balance改名为了_Account__balance(名称改写),虽然硬要访问也能访问,但君子协定我们要遵守规则。


二、继承 (Inheritance):子承父业

2.1 为什么要继承?

假设我们要写CatDog两个类,它们都有name属性,都会eat。如果分别写两个类,代码就重复了。
我们可以提取一个父类Animal,让CatDog去继承它。

2.2 定义继承

# 父类 (基类)classAnimal:def__init__(self,name):self.name=namedefeat(self):print(f"{self.name}正在吃饭...")defsleep(self):print(f"{self.name}正在睡觉...")# 子类 (派生类) 继承 AnimalclassDog(Animal):defbark(self):print("汪汪汪!")classCat(Animal):defmeow(self):print("喵喵喵!")# 测试dog=Dog("旺财")dog.eat()# 继承自父类的方法 -> 旺财 正在吃饭...dog.bark()# 子类独有的方法 -> 汪汪汪!

2.3 方法重写 (Overriding)

如果子类对父类的方法不满意,可以重新定义它。

classBird(Animal):defeat(self):print(f"{self.name}正在啄米吃...")# 重写父类的 eatbird=Bird("波利")bird.eat()# 波利 正在啄米吃...

2.4 super() 函数

在子类中,如果想调用父类的方法(特别是在__init__中),需要用到super()

classDog(Animal):def__init__(self,name,breed):# 调用父类的 __init__ 初始化 namesuper().__init__(name)# 再初始化子类独有的 breedself.breed=breed d=Dog("来福","哈士奇")print(f"{d.name}{d.breed}")

三、多态 (Polymorphism):一种接口,多种形态

3.1 什么是多态?

多态是指:不同的子类对象调用相同的父类方法,产生不同的执行结果。

classAnimal:defspeak(self):passclassDog(Animal):defspeak(self):print("汪汪!")classCat(Animal):defspeak(self):print("喵喵!")defmake_noise(animal_obj):"""这个函数接收任何 Animal 对象"""animal_obj.speak()d=Dog("A")c=Cat("B")make_noise(d)# 汪汪!make_noise(c)# 喵喵!

3.2 鸭子类型 (Duck Typing)

Python 是一种动态语言,它并不严格要求继承体系。
“如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子。”

哪怕一个类没有继承Animal,只要它也有speak()方法,上面的make_noise函数照样能处理它。

classCar:defspeak(self):print("滴滴!")car=Car()make_noise(car)# 滴滴! (Python 不检查类型,只检查有没有这个方法)

四、实战练习

练习1:工资管理系统 (继承与多态)

  1. 定义父类Employee,属性name,方法get_pay()
  2. 定义子类FullTimeEmployee,属性salary(月薪),重写get_pay()返回月薪。
  3. 定义子类PartTimeEmployee,属性hours,rate(时薪),重写get_pay()返回hours * rate
  4. 编写一个函数计算公司所有员工的总工资。
classEmployee:def__init__(self,name):self.name=namedefget_pay(self):return0classFullTimeEmployee(Employee):def__init__(self,name,salary):super().__init__(name)self.salary=salarydefget_pay(self):returnself.salaryclassPartTimeEmployee(Employee):def__init__(self,name,hours,rate):super().__init__(name)self.hours=hours self.rate=ratedefget_pay(self):returnself.hours*self.rate# 统计总支出staffs=[FullTimeEmployee("Alice",6000),FullTimeEmployee("Bob",8000),PartTimeEmployee("Charlie",50,20)# 50小时 * 20元 = 1000]total_pay=sum(emp.get_pay()forempinstaffs)print(f"公司本月总工资支出:{total_pay}")# 15000

五、OOP 类图结构

我们可以用 Mermaid 来直观地展示继承关系。

继承

继承

Animal

+name

+eat()

+sleep()

Dog

+bark()

Cat

+meow()


六、常见问题

Q1:私有方法怎么定义?

和属性一样,方法名前加双下划线。例如def __secret_method(self):,只能在类内部被self.__secret_method()调用。

Q2:Python 支持多继承吗?

支持。class C(A, B):表示 C 同时继承 A 和 B。但这会带来复杂性(如菱形继承问题),初学者建议先掌握单继承。

Q3:isinstance是什么?

用来判断对象是否属于某个类。

d=Dog("A")print(isinstance(d,Dog))# Trueprint(isinstance(d,Animal))# True (因为Dog继承Animal)print(isinstance(d,Cat))# False

七、小结

OOP 三大特性

封装 Encapsulation

继承 Inheritance

多态 Polymorphism

私有属性 __attr

公开方法访问

class Child(Parent)

代码复用

super() 调用父类

同名方法,不同实现

鸭子类型

关键要点

  1. 封装:用__隐藏内部细节,提供安全接口。
  2. 继承:子类自动拥有父类的功能,super()是连接父子的桥梁。
  3. 多态:让代码更灵活,关注点从"是什么类型"转变为"能做什么"。

八、课后作业

  1. 图形计算器
    • 定义父类Shape,有一个方法area()返回 0。
    • 定义子类Circle(属性半径) 和Square(属性边长)。
    • 分别重写area()方法。
    • 创建一个列表包含不同的图形,遍历打印它们的面积。
  2. 游戏角色
    • 定义Hero类,包含hp(血量) 和attack()方法。
    • 定义Mage(法师) 和Warrior(战士) 继承Hero
    • 法师攻击时打印"释放火球",战士攻击时打印"挥舞大剑"。
    • 尝试给法师增加一个mp(魔法值) 属性,并在攻击时消耗魔法。

下节预告

Day 16:面向对象编程(OOP)下篇 - 魔术方法与类属性-__str__是什么?__add__是什么?静态方法又是什么?明天我们将探索类的更多高级玩法!


系列导航

  • 上一篇:Day 14 - 面向对象编程(上)
  • 下一篇:Day 16 - 面向对象编程(下)(待更新)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1146253.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

差分放大器在Multisim仿真电路图中的实战案例

差分放大器实战:用Multisim搭建高精度信号调理前端你有没有遇到过这样的情况?传感器输出的微弱信号刚进放大电路,就被工频干扰淹没;示波器上本该是平滑正弦波的输出,却出现了削顶失真;明明理论增益是10倍&a…

三脚电感布局布线对EMI性能的影响研究

三脚电感布局布线对EMI性能的影响研究:从理论到实战的深度解析当电子系统“吵”起来时,谁在负责降噪?在今天的电子产品设计中,我们常常追求更高的效率、更小的体积和更低的功耗。但当这些目标达成的同时,一个问题却悄然…

vivado许可证与高级综合(HLS)工具集成要点

从代码到硅片:绕不开的 Vivado 许可证与 HLS 集成实战指南 你有没有遇到过这样的场景? 写好了一段 C 算法,信心满满地打开 Vivado HLS,准备一键综合成硬件 IP。结果刚运行 open_solution ,控制台就跳出一行红字&am…

逻辑门组合电路设计:超详细版基础入门指南

从零开始学数字电路:用逻辑门搭建你的第一个组合电路你有没有想过,手机里每秒执行数十亿条指令的处理器,其实是由最简单的“开关”一步步搭起来的?这些“开关”不是物理按钮,而是我们今天要讲的主角——逻辑门。在嵌入…

图解说明交叉编译工具链与驱动二进制生成过程

深入理解交叉编译:从驱动源码到ARM板上运行的.ko模块你有没有遇到过这样的场景?在x86_64的Linux电脑上写好了一个设备驱动,兴冲冲地拷贝到树莓派上执行insmod hello_driver.ko,结果系统报错:insmod: ERROR: could not …

电商市场的用户反馈分析与应用

电商市场的用户反馈分析与应用 关键词:电商市场、用户反馈分析、文本挖掘、情感分析、数据应用 摘要:本文聚焦于电商市场的用户反馈分析与应用。在电商行业竞争日益激烈的当下,用户反馈蕴含着巨大的价值。通过对用户反馈的深入分析,电商企业能够了解用户需求、改进产品与服…

AI原生应用语音合成:重塑语音导航体验

AI原生应用语音合成:重塑语音导航体验 关键词:AI原生应用、语音合成(TTS)、神经语音合成、多模态交互、导航体验升级 摘要:当你开车时,导航语音从“机械电子音”变成“好友的声音”,甚至能根据路…

时序逻辑电路设计实验:Multisim仿真操作指南

时序逻辑电路设计实验:从理论到Multisim仿真的实战之路你有没有试过在面包板上搭一个计数器,结果按下按钮后LED乱闪、状态跳变错乱?或者明明逻辑图是对的,可就是数不到“6”就回零——这种令人抓狂的调试经历,在数字电…

一、爬虫-控制台介绍

Element:元素面板,前端静态或者动态渲染后的,不一定是源码Console:控制台,显示日志信息和执行js命令Sources:资源 左边: Page:源代码Workspace:工作空间Overrides&#x…

如何通过数据分析提升销售额

如何通过数据分析提升销售额 关键词:数据分析、销售额提升、数据挖掘、销售策略、客户行为分析 摘要:本文围绕如何通过数据分析提升销售额展开。详细阐述了数据分析在销售领域的核心概念、算法原理、数学模型,通过具体的项目实战案例展示了如何运用数据分析解决实际销售问题…

电源管理芯片同步整流技术深度剖析其硬件实现

同步整流如何让电源效率“起飞”?——从MOSFET到PMIC的硬核拆解你有没有想过,为什么现在的手机充电越来越快、待机越来越久,而机身却还能越做越薄?背后的功臣之一,正是藏在主板深处、默默工作的电源管理芯片&#xff0…

大数据领域分布式存储的存储性能优化技巧

大数据领域分布式存储的存储性能优化技巧:从"数据仓库"到"超级快递站"的升级指南 关键词:分布式存储、性能优化、数据分片、一致性协议、IO路径优化、副本机制、硬件加速 摘要:在大数据时代,分布式存储就像一…

【前端修仙之路】CSS:告别毛坯房,给你的网页穿上“华丽外衣”

你好,准前端艺术家!在上一篇文章中,我们用 HTML 搭建了网页的骨架。但说实话,现在的网页看起来可能有点……惨不忍睹(就像是 90 年代的黑白报纸)。今天我们要学习的 CSS(层叠样式表)…

高频信号下三极管放大区性能变化:全面讲解频率响应特性

高频之下,三极管还“能放大”吗?——深入解析BJT在放大区的频率极限你有没有遇到过这样的情况:电路原理图设计得完美无缺,小信号增益计算高达50 dB,可一上电测试,高频段增益却断崖式下跌,甚至输…

可配置位宽的RISC-V ALU RTL实现方案

一次设计,多处部署:深入实现可配置位宽的 RISC-V ALU在嵌入式系统、边缘计算和定制化处理器架构蓬勃发展的今天,我们对 CPU 核心的要求早已不再局限于“能跑通代码”。性能、功耗、面积(PPA)的精细权衡,以及…

Day 16:【99天精通Python】面向对象编程(OOP)下篇 - 魔术方法与类属性

Day 16:【99天精通Python】面向对象编程(OOP)下篇 - 魔术方法与类属性 前言 欢迎来到第16天! 在之前的两天里,我们构建了 OOP 的大厦框架。今天,我们要进行内部装修,学习一些 Python 特有的"黑魔法"。 你是否…

不同PWM频率下无源蜂鸣器声音效果对比分析

PWM频率如何“调教”无源蜂鸣器?一次听觉与物理的深度对话你有没有过这样的经历:在调试一个报警系统时,明明代码跑通了,蜂鸣器也“响”了,但声音却像是从老旧收音机里传出来的——低沉、模糊、甚至带点嗡嗡的震动感&am…

TI TPS系列在工业控制中的电源管理解决方案详解

工业控制电源设计的“隐形冠军”:TI TPS系列芯片实战解析在工业自动化现场,你可能见过这样的场景:一台PLC连续运行数年无故障,传感器节点在荒野中靠电池撑过三年未更换,高速数据采集系统在强电磁干扰下依然输出稳定信号…

OpenAMP RPMsg驱动架构全面讲解

OpenAMP RPMsg驱动架构深度解析:从原理到实战的完整指南在现代嵌入式系统中,“一个芯片跑多个操作系统”已不再是科幻场景。无论是智能音箱里的音频实时处理,还是工业PLC中的高精度电机控制,亦或是自动驾驶域控制器内的传感器融合…

Kafka从入门到入门

kafka的出现是为了支持大量消息事件,它的分布式设计、消息抽象设计及存储选择和优化性能手段都高效的支持了它的性能表现,同时面临分布式系统典型的信息同步、中心化设计、负载均衡等问题,对于这些问题kafka也给出了高效和多样化的选择&#…