PYTHON LESSON 055
电子宠物养成记
认识类与对象,会用 __init__ 创建带属性的对象,会定义和调用方法。
00 · 学习目标
这一课要解决什么?
学完后,你应该能够
- class 类名: 画出一张图纸
- __init__ 创建对象时自动执行
- 对象.方法() 让对象自己做事
01 · 核心概念
类的创建:__init__、属性与方法
类的创建:__init__、属性与方法:类(class)是一张图纸,规定“宠物”都有什么属性、会做什么事;对象是按图纸造出来的具体产品。一张图纸可以造出千千万万只宠物,每只都有自己的数值。
GESP Python 4 级 · 类的创建课程使用普通类解释对象模型;dataclass、property、抽象基类和元类是后续工程工具。
02 · 语法与规则
先记住这 3 条,再开始写程序
class 类名: 画出一张图纸先准确读出这条写法的结构与作用。
__init__ 创建对象时自动执行换一组最小数据,手工推演一次结果。
对象.方法() 让对象自己做事再用边界值或反例确认它的适用条件。
03 · 完整实例
代码、运行结果和解释放在一起看
# 电子宠物养成记:类的创建
class Pet:
"""一只电子宠物:有名字、种类、饥饿值和心情值"""
def __init__(self, name, kind):
self.name = name # 属性:名字
self.kind = kind # 属性:种类
self.hunger = 50 # 属性:饥饿值(越大越饿)
self.mood = 50 # 属性:心情值
def feed(self):
"""喂食:饥饿值下降"""
self.hunger = self.hunger - 20
print(f"{self.name}吃饱了,饥饿值降到 {self.hunger}")
def play(self):
"""玩耍:心情值上升,饥饿值上升"""
self.mood = self.mood + 15
self.hunger = self.hunger + 10
print(f"{self.name}玩得很开心,心情 {self.mood},饥饿 {self.hunger}")
def status(self):
"""汇报当前状态"""
print(f"[{self.kind}]{self.name}:饥饿 {self.hunger},心情 {self.mood}")
# 按图纸(类)造出两只宠物(对象)
cat = Pet("咪咪", "小猫")
dog = Pet("旺财", "小狗")
cat.feed()
cat.play()
dog.play()
cat.status()
dog.status()咪咪吃饱了,饥饿值降到 30 咪咪玩得很开心,心情 65,饥饿 40 旺财玩得很开心,心情 65,饥饿 60 [小猫]咪咪:饥饿 40,心情 65 [小狗]旺财:饥饿 60,心情 65
self 指“这只宠物自己”:每个对象的属性各存一份,互不干扰。
04 · 逐步理解
每一步只解决一个问题
- 01
类是图纸,对象是产品
类(class)是一张图纸,规定“宠物”都有什么属性、会做什么事;对象是按图纸造出来的具体产品。一张图纸可以造出千千万万只宠物,每只都有自己的数值。
class Pet: - 02
__init__:出生证明
Pet("咪咪", "小猫") 一执行,__init__ 自动运行,把名字、种类写在这只宠物的“出生证明”上,并给饥饿值、心情值赋上初始值 50。
def __init__(self, name, kind): self.name = name self.kind = kind - 03
self 是“我自己”
每个方法的第一个参数都叫 self,指“这个对象自己”。cat.feed() 执行时,self 就是 cat,改的是 cat 的饥饿值;dog.feed() 时 self 就是 dog。self 让同一份代码服务每一只宠物。
self.hunger = self.hunger - 20 - 04
方法就是对象会做的事
方法和函数长得一样,只是写在类里面、第一个参数是 self。feed、play、status 定义了宠物的本领;用“对象.方法()”的格式让它施展本领。
cat.feed() cat.status() - 05
两只宠物,互不干扰
cat 玩耍后心情 65,dog 玩耍后也是 65——各自从 50 算起。属性存在每个对象自己身上,这正是类最强大的地方:批量管理“同一类东西,各有各的数据”。
- 06
给宠物加技能
试着给 Pet 加一个新方法 sleep():心情 +10、饥饿 +5。再养一只 Pet("团团", "熊猫"),喂它、陪它玩,最后用 status() 验收你的宠物乐园。
def sleep(self): self.mood = self.mood + 10
05 · 练习与检验
自己写出来,才算真正学会
- 1运行程序,养出小猫和小狗
- 2再养第三只宠物,互不影响
- 3给宠物加一个新方法 sleep
- 4连续喂食三次,观察饥饿值变化
06 · 完整知识
继续理解定义、规则和适用边界
第一次学习先完成上面的六个步骤;需要查定义、核对规则、分析误区或理解“为什么”时,再展开对应知识章。
程序组织类、对象、属性与方法理解对象模型和封装边界,用类表达有状态的实体,而不是把所有程序都强行改成类。+
正式定义
类描述一类对象的数据与行为;实例是类创建的具体对象。实例方法的第一个参数通常命名为 self,用来访问当前实例;__init__ 在实例创建后负责初始化状态。
必须掌握
- 实例属性通常在 __init__ 中通过 self.name = value 建立。
- 实例方法通过 object.method() 调用;Python 会自动把实例绑定给 self。
- 类属性由实例共享,实例属性属于单个对象;同名实例属性会遮蔽类属性。
- __repr__ 面向开发与调试,__str__ 面向用户显示;特殊方法应遵守其协议。
- 继承表达“是一种”关系,组合表达“拥有一个”关系;能用组合清晰表达时不要滥用继承。
- 对象相等默认仍是身份比较;需要按内容相等时要定义相应协议。
常见误区
- 在方法中漏写 self
- 把每个实例独有的可变数据写成类属性
- 只为包装几个无状态函数而建类
- 继承层次过深导致行为难以追踪
适用边界
- 课程使用普通类解释对象模型;dataclass、property、抽象基类和元类是后续工程工具。
- 算法题常用函数和基本容器更直接,不要求为了“面向对象”而增加结构。
程序组织函数、参数、返回值与作用域用明确的输入、输出和职责拆分程序,理解参数绑定、作用域、递归与可变对象。+
正式定义
函数把一段可复用行为绑定到名字。调用时实参按规则绑定到形参,函数执行后用 return 交回结果;没有显式 return 时返回 None。名字解析遵循局部、闭包、全局、内置的 LEGB 顺序。
必须掌握
- 位置参数先于关键字参数;默认值在 def 执行时创建一次,不应直接使用可变容器作默认值。
- return 立即结束当前函数;return a, b 实际返回一个元组。
- 函数内赋值默认创建局部变量;global 声明模块级名字,nonlocal 声明最近外层函数名字。
- 传参传递的是对象引用;函数是否影响调用方取决于对象是否可变以及函数是否原地修改。
- 递归必须有可到达的终止条件,并要考虑调用深度、重复子问题和栈空间。
- 纯函数更容易测试;把输入输出、计算逻辑和全局状态分开能显著减少错误。
常见误区
- 可变默认参数在多次调用间共享
- 忘记 return 导致得到 None
- 局部变量遮蔽全局同名变量
- 递归没有缩小问题规模
适用边界
- lambda 只能包含一个表达式,适合短小的排序键,不适合塞入复杂业务逻辑。
- 装饰器、生成器和闭包属于函数模型的进阶应用,应在基本参数与作用域稳定后学习。
核心数据结构树、图、DFS、BFS 与最短路从节点与边的模型出发,掌握遍历、连通性、树结构、最小生成树和最短路径的适用条件。+
正式定义
图由顶点和边构成;树是连通且无环的无向图。DFS 沿路径深入后回溯,BFS 按距离层次扩展。算法的正确选择取决于图是否有向、边权是否为负、是否稠密以及目标是遍历、连通还是最短路。
必须掌握
- 邻接矩阵占 O(V²) 空间,适合稠密图和快速查边;邻接表占 O(V+E),适合稀疏图。
- DFS 常用递归或显式栈,BFS 使用队列;一般图都必须记录 visited 防止重复和死循环。
- 无权图的 BFS 首次到达即得到最少边数距离,可用 parent 还原路径。
- 树有 V-1 条边且任意两点路径唯一;二叉树前/中/后序描述根的访问时机。
- Dijkstra 只适用于非负边权;Floyd 求所有点对最短路并允许负边,但不能有可达负环。
- Kruskal 按边权排序并用并查集避环,得到连通无向带权图的最小生成树。
常见误区
- 遍历一般图时不记录 visited
- 对负权边使用 Dijkstra
- 混淆最短路径树与最小生成树
- 递归 DFS 忽略深度限制
适用边界
- 有向无环图、拓扑排序、强连通分量和负权最短路是图论后续主题。
- 网格搜索也是图搜索:格子是顶点,可移动关系是边;不要只背二维数组模板。
完整速查Python 关键字、内置名称与语法速查集中查阅 Python 3.12 的 35 个硬关键字、4 个软关键字和课程常用内置函数,避免知识碎片化。+
正式定义
关键字是 Python 语法保留的词,不能作为普通标识符;软关键字只在特定语法位置有特殊含义。内置名称由 builtins 模块提供,可以直接使用,但仍可能被同名变量遮蔽。
必须掌握
- Python 3.12 有 35 个硬关键字;False、None、True 首字母大写。
- match、case、_、type 是软关键字,只在对应模式匹配或类型参数语法环境中特殊。
- 内置函数无需 import,但不要把变量命名为 list、str、sum、max、input 等。
- help(name) 查看运行时帮助,dir(object) 查看可用名称,type(object) 查看类型。
- 内置异常类也是内置名称;捕获异常时应使用具体异常类型。
- 本站课程运行基线是 Python 3.12,跨版本新增语法必须先核对目标运行环境。
常见误区
- 把内置名称误称为关键字
- 用 list = [] 遮蔽 list()
- 照搬其他 Python 版本的关键字表
- 见到陌生函数名就假定无需导入
适用边界
- 本页完整列出语言关键字,并列出课程实际依赖的内置函数;Python 的全部内置异常类和对象协议应按具体错误与主题查阅。
- 第三方库 API 不属于 Python 语言本身,也不属于内置名称。
完成检查