零基础学 Python 第18章 | 多态与魔法方法:让对象更智能
本章摘要
- 核心目标:掌握多态与魔法方法,让自定义对象支持
print输出、len()统计和运算符操作 - 核心知识点:多态概念与实现、
__str__、__repr__、__len__、__add__运算符重载、__eq__比较重载 - 实操产出:迷你图书管理系统,综合运用类定义、继承、封装、多态、魔法方法、文件读写
- 前置基础:第17章封装、第16章继承、第15章类与对象
一、写在前面
上一章学了封装,你学会了用私有属性和 @property 保护数据,让对象像一个"黑盒子"——外面只能通过规定的方法操作,不能乱改内部状态。封装让代码更安全、更规范。
但你可能发现两个问题:第一,print(对象) 输出的结果是一串看不懂的内存地址 <__main__.Student object at 0x7f...>,一点也不友好;第二,两个对象相加 obj1 + obj2 直接报错,比较相等 obj1 == obj2 比的也是内存地址,不是我们想要的内容。
这两个问题的根源是一样的:Python 不知道你的对象该怎么打印、怎么相加、怎么比较。魔法方法(Magic Methods)就是来解决这些问题的——你只需要在类里定义几个特殊方法,Python 就会自动调用它们,让你的对象像内置类型一样好用。
本章还会讲到面向对象的最后一个特性——多态。多态和魔法方法其实是"一体两面":魔法方法本身就是多态的体现,print() 对不同对象调用各自的 __str__(),输出完全不同的结果。
二、多态:同名方法,不同行为
2.1 什么是多态
多态一句话概括:不同的对象调用同名方法,表现出不同的行为。
举个例子:你喊"叫一声",狗会"汪汪汪",猫会"喵喵喵",鸭子会"嘎嘎嘎"。同样是 speak() 方法,不同动物有不同表现——这就是多态。
2.2 多态的代码实现
多态通常通过继承 + 方法重写来实现。子类继承父类后,重写父类的方法,调用时根据对象类型自动选择对应的方法:
# 父类
class Animal:
def speak(self):
print("动物发出声音")
# 子类重写 speak()
class Dog(Animal):
def speak(self):
print("汪汪汪!")
class Cat(Animal):
def speak(self):
print("喵喵喵!")
# 多态:同一个函数,传入不同对象,行为不同
def make_sound(animal):
animal.speak()
# 传入不同的对象,输出不同的结果
make_sound(Dog()) # 汪汪汪!
make_sound(Cat()) # 喵喵喵!
make_sound(Animal()) # 动物发出声音
运行结果:
汪汪汪!
喵喵喵!
动物发出声音
关键点:make_sound() 函数不关心传入的是 Dog 还是 Cat,只要对象有 speak() 方法就行。传什么对象,就调用什么对象的 speak()——这就是多态的威力。
2.3 鸭子类型
Python 的多态有个独特之处叫鸭子类型(Duck Typing),来自一句俗语:
“如果一只鸟走起来像鸭子、叫起来像鸭子,那它就是鸭子。”
意思是 Python 不关心对象的类型是什么,只关心它有没有需要的方法。不需要继承同一个父类,只要有同名方法就能多态:
class Dog:
def speak(self):
print("汪汪汪!")
class Robot:
def speak(self):
print("嘀嘀嘀,我是机器人")
def make_sound(animal):
animal.speak()
# Dog 和 Robot 没有继承关系,但都有 speak() 方法
make_sound(Dog()) # 汪汪汪!
make_sound(Robot()) # 嘀嘀嘀,我是机器人
运行结果:
汪汪汪!
嘀嘀嘀,我是机器人
Dog 和 Robot 没有继承关系,但都有 speak() 方法,make_sound() 照样能正常工作。这就是 Python 的灵活性——不看出身,只看能力。
其他语言(如 Java)要求必须继承同一个父类或实现同一个接口才能多态,Python 不需要,有同名方法就行。
三、__str__:让 print 输出更好看
3.1 默认打印的问题
先看一个问题:创建一个学生对象,打印它:
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
s = Student("小明", 18)
print(s)
运行结果:
<__main__.Student object at 0x7f8b2c3d4e50>
这串输出谁看得懂?0x7f8b2c3d4e50 是对象在内存中的地址,每次运行都不一样。我们希望 print(s) 能直接显示学生信息,这就需要 __str__ 方法。
3.2 自定义 str
在类中定义 __str__ 方法,返回一个字符串,print(对象) 时 Python 会自动调用它:
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"学生:{self.name},{self.age}岁"
s = Student("小明", 18)
print(s) # 学生:小明,18岁
print(str(s)) # 学生:小明,18岁(str() 也调用 __str__)
运行结果:
学生:小明,18岁
学生:小明,18岁
定义了 __str__ 之后,print(s) 不再输出内存地址,而是输出我们指定的格式化字符串。
规则:
__str__必须返回字符串,返回其他类型会报错。
这就是多态的体现——print() 函数对不同类型的对象调用各自的 __str__:整数输出数字,字符串原样输出,自定义对象输出我们定义的内容。
四、__repr__:给开发者看的信息
4.1 __repr__ 的作用
__repr__ 和 __str__ 类似,也是控制对象打印时的输出,但用途不同:
__str__:给用户看,追求可读性,print(obj)时调用__repr__:给开发者看,追求准确性,repr(obj)或在交互式环境中直接输入变量名时调用
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"学生:{self.name},{self.age}岁"
def __repr__(self):
return f"Student('{self.name}', {self.age})"
s = Student("小明", 18)
print(s) # 学生:小明,18岁 ← __str__
print(repr(s)) # Student('小明', 18) ← __repr__
运行结果:
学生:小明,18岁
Student('小明', 18)
4.2 __str__ 与 __repr__ 的区别
| 对比项 | __str__ |
__repr__ |
|---|---|---|
| 调用方式 | print(obj) / str(obj) |
repr(obj) / 交互式直接输入 |
| 目标读者 | 普通用户 | 开发者 |
| 风格 | 可读性好,像句子 | 准确,尽量像合法代码 |
| 列表中 | 不生效 | 生效,列表元素用 __repr__ |
一个重要细节:把对象放在列表中打印时,Python 用的是 __repr__ 而不是 __str__:
students = [Student("小明", 18), Student("小红", 20)]
print(students)
运行结果:
[Student('小明', 18), Student('小红', 20)]
如果只定义了 __str__ 没定义 __repr__,列表中的对象会显示成内存地址。所以调试时建议两个都定义。
如果只定义一个,优先定义
__str__。但开发中最佳实践是两个都写:__str__给用户看,__repr__给自己看。
五、__len__:让 len() 支持自定义对象
内置函数 len() 可以统计列表、字符串、字典的长度。自定义对象默认不能用 len(),会报错。定义 __len__ 方法后就可以了:
class Classroom:
def __init__(self, name):
self.name = name
self.students = []
def add_student(self, name):
self.students.append(name)
def __len__(self):
return len(self.students)
room = Classroom("三年级二班")
room.add_student("小明")
room.add_student("小红")
room.add_student("小刚")
print(len(room)) # 3
运行结果:
3
定义了 __len__ 后,len(room) 直接返回学生人数,和 len([1, 2, 3]) 用法完全一样。
__len__必须返回一个整数,返回其他类型会报错。
这也是多态:len() 对列表返回元素个数,对字符串返回字符数,对自定义对象返回 __len__ 的返回值——同一个函数,不同行为。
六、运算符重载:让对象支持运算
运算符重载就是让自定义对象支持 +、-、== 等运算符。方法很简单:在类中定义对应的魔法方法。
6.1 __add__:让对象相加
默认情况下,两个自定义对象不能相加,会报 TypeError。定义 __add__ 后,obj1 + obj2 就会调用这个方法:
class Money:
def __init__(self, amount, currency="CNY"):
self.amount = amount
self.currency = currency
def __add__(self, other):
# 只允许相同币种相加
if self.currency != other.currency:
raise ValueError("币种不同,无法相加")
return Money(self.amount + other.amount, self.currency)
def __str__(self):
return f"{self.amount} {self.currency}"
price1 = Money(50)
price2 = Money(30)
total = price1 + price2 # 调用 price1.__add__(price2)
print(total) # 80 CNY
运行结果:
80 CNY
price1 + price2 实际上调用的是 price1.__add__(price2)。__add__ 返回一个新的 Money 对象,所以 total 也是一个 Money 对象,print(total) 调用它的 __str__ 输出结果。
__add__的参数other就是加号右边的对象。返回值可以是新对象,也可以是其他类型,根据需求决定。
6.2 __eq__:让对象比较相等
默认情况下,== 比较的是两个对象的内存地址(和 is 一样)。两个内容相同但独立创建的对象,== 返回 False:
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
s1 = Student("小明", 18)
s2 = Student("小明", 18)
print(s1 == s2) # False(默认比较内存地址)
print(s1 is s2) # False(两个独立对象)
定义 __eq__ 后,可以自定义比较规则:
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
# 先判断类型,避免和字符串等比较时报错
if isinstance(other, Student):
return self.name == other.name and self.age == other.age
return False
def __str__(self):
return f"学生:{self.name},{self.age}岁"
s1 = Student("小明", 18)
s2 = Student("小明", 18)
s3 = Student("小红", 18)
print(s1 == s2) # True(姓名和年龄都相同)
print(s1 == s3) # False(姓名不同)
print(s1 == "小明") # False(类型不同,安全返回 False)
运行结果:
True
False
False
重要提醒:
__eq__中比较属性时用self.name == other.name,不要写self == other,否则会无限递归调用__eq__直到栈溢出。
6.3 其他常用魔法方法速查
除了上面讲的,Python 还有很多魔法方法,原理都一样——定义了就能用对应的运算:
| 魔法方法 | 触发运算 | 说明 |
|---|---|---|
__add__(self, other) |
a + b |
加法 |
__sub__(self, other) |
a - b |
减法 |
__mul__(self, other) |
a * b |
乘法 |
__eq__(self, other) |
a == b |
等于 |
__ne__(self, other) |
a != b |
不等于 |
__lt__(self, other) |
a < b |
小于 |
__gt__(self, other) |
a > b |
大于 |
__le__(self, other) |
a <= b |
小于等于 |
__ge__(self, other) |
a >= b |
大于等于 |
__len__(self) |
len(a) |
长度 |
__str__(self) |
print(a) / str(a) |
用户友好字符串 |
__repr__(self) |
repr(a) |
开发者字符串 |
__contains__(self, item) |
item in a |
成员判断 |
__bool__(self) |
bool(a) / if a: |
布尔值 |
# 综合示例:一个支持比较的成绩类
class Score:
def __init__(self, name, value):
self.name = name
self.value = value
def __add__(self, other):
return Score(f"{self.name}+{other.name}", self.value + other.value)
def __eq__(self, other):
if isinstance(other, Score):
return self.value == other.value
return False
def __gt__(self, other):
return self.value > other.value
def __str__(self):
return f"{self.name}:{self.value}分"
math = Score("数学", 90)
english = Score("英语", 85)
total = math + english
print(total) # 数学+英语:175分
print(math > english) # True(90 > 85)
print(math == Score("数学", 90)) # True(分数相同)
运行结果:
数学+英语:175分
True
True
不需要全部记住,用到的时候查表就行。最常用的是
__str__、__repr__、__eq__和__len__。
七、Scratch 积木对照
本章涉及的多态和魔法方法属于 Python 高阶特性,Scratch 中没有对应的积木概念,不硬凑对照。
Scratch 中没有"类"“对象”"方法重写"等概念,也没有运算符重载机制。这些是面向对象编程的核心特性,需要用 Python 的语法来理解和实践。不过你可以这样类比:Scratch 中"说"积木能显示文字,而 Python 中 print() 调用 __str__ 输出对象信息——都是"告诉别人自己是什么"的意思。
八、综合实战:迷你图书管理系统(全书收官案例)
这是全书的最后一个综合案例。它综合运用了 类定义、继承、封装、多态、魔法方法、文件读写 ——你学过的面向对象知识,这里全部用上。
系统设计
| 类 | 职责 | 用到的知识点 |
|---|---|---|
Book |
图书基类,记录书名/作者/借出状态 | 封装、__str__、__repr__、__eq__ |
EBook |
电子书,继承 Book,增加下载链接 |
继承、多态(重写 __str__) |
User |
读者,记录姓名/借书列表,支持借还 | 封装、__str__、__len__ |
Library |
图书馆,管理图书和读者,支持文件存取 | 多态、__len__、__str__、文件读写 |
完整源码
# ========================================
# 迷你图书管理系统 - 全书收官综合案例
# ========================================
class Book:
"""图书基类"""
def __init__(self, title, author):
self._title = title # 封装:书名设为私有
self._author = author # 封装:作者设为私有
self._borrowed = False # 封装:借出状态设为私有
@property
def title(self):
return self._title
@property
def author(self):
return self._author
@property
def borrowed(self):
return self._borrowed
def borrow(self):
self._borrowed = True
def return_book(self):
self._borrowed = False
def __str__(self):
# 魔法方法:print(book) 时显示友好信息
status = "已借出" if self._borrowed else "可借阅"
return f"《{self._title}》- 作者:{self._author} [{status}]"
def __repr__(self):
# 魔法方法:开发者调试时看到的信息
return f"Book('{self._title}', '{self._author}')"
def __eq__(self, other):
# 魔法方法:两本书书名和作者都相同就视为同一本书
if isinstance(other, Book):
return self._title == other._title and self._author == other._author
return False
class EBook(Book):
"""电子书,继承自 Book"""
def __init__(self, title, author, url):
super().__init__(title, author) # 调用父类初始化
self._url = url # 电子书独有的下载链接
# 多态:重写 __str__,输出格式和普通图书不同
def __str__(self):
status = "已借出" if self._borrowed else "可借阅"
return f"《{self._title}》- 作者:{self._author} [电子书|{status}]"
class User:
"""读者类"""
def __init__(self, name):
self._name = name
self._borrowed_books = [] # 借阅记录
@property
def name(self):
return self._name
def borrow_book(self, book):
"""借书"""
if book.borrowed:
print(f" ❌ 《{book.title}》已被借出")
return False
book.borrow()
self._borrowed_books.append(book)
print(f" ✅ {self._name} 成功借阅《{book.title}》")
return True
def return_book(self, book):
"""还书"""
if book in self._borrowed_books:
book.return_book()
self._borrowed_books.remove(book)
print(f" ✅ {self._name} 已归还《{book.title}》")
return True
print(f" ❌ {self._name} 没有借阅《{book.title}》")
return False
def show_borrowed(self):
"""查看已借图书"""
if not self._borrowed_books:
print(f" {self._name} 当前没有借阅任何图书")
else:
print(f" {self._name} 借阅了 {len(self._borrowed_books)} 本:")
for book in self._borrowed_books:
print(f" {book}") # 多态:Book 和 EBook 各自调用 __str__
def __str__(self):
return f"读者:{self._name}(已借{len(self._borrowed_books)}本)"
def __len__(self):
return len(self._borrowed_books)
class Library:
"""图书馆类"""
def __init__(self, name="社区图书馆"):
self._name = name
self._books = []
self._users = []
def add_book(self, book):
self._books.append(book)
def add_user(self, user):
self._users.append(user)
def find_book(self, title):
"""按书名查找图书"""
for book in self._books:
if book.title == title:
return book
return None
def find_user(self, name):
"""按姓名查找读者"""
for user in self._users:
if user.name == name:
return user
return None
def borrow(self, user_name, book_title):
"""借书操作"""
user = self.find_user(user_name)
book = self.find_book(book_title)
if user is None:
print(f" ❌ 读者 {user_name} 不存在")
return
if book is None:
print(f" ❌ 图书《{book_title}》不存在")
return
user.borrow_book(book)
def return_book(self, user_name, book_title):
"""还书操作"""
user = self.find_user(user_name)
book = self.find_book(book_title)
if user is None:
print(f" ❌ 读者 {user_name} 不存在")
return
if book is None:
print(f" ❌ 图书《{book_title}》不存在")
return
user.return_book(book)
def show_all_books(self):
"""显示所有图书(多态展示)"""
print(f"\n📚 {self._name} 藏书列表(共 {len(self._books)} 本):")
for book in self._books:
print(f" {book}") # 多态:Book 输出普通格式,EBook 输出电子书格式
def show_all_users(self):
"""显示所有读者"""
print(f"\n👥 读者列表(共 {len(self._users)} 人):")
for user in self._users:
print(f" {user}")
def save_to_file(self, filename="library_data.txt"):
"""保存图书数据到文件"""
with open(filename, "w", encoding="utf-8") as f:
for book in self._books:
# 格式:类型,书名,作者,借出状态
book_type = "EBook" if isinstance(book, EBook) else "Book"
f.write(f"{book_type},{book.title},{book.author},{book.borrowed}\n")
print(f" ✅ 数据已保存到 {filename}")
def load_from_file(self, filename="library_data.txt"):
"""从文件加载图书数据"""
try:
with open(filename, "r", encoding="utf-8") as f:
for line in f:
parts = line.strip().split(",")
if len(parts) >= 4:
book_type, title, author, borrowed = parts[0], parts[1], parts[2], parts[3]
if book_type == "EBook":
book = EBook(title, author, "http://example.com/download")
else:
book = Book(title, author)
if borrowed == "True":
book.borrow()
self._books.append(book)
print(f" ✅ 已从 {filename} 加载图书数据")
except FileNotFoundError:
print(f" ⚠️ 文件 {filename} 不存在,从空库开始")
def __len__(self):
# 魔法方法:len(library) 返回藏书数量
return len(self._books)
def __str__(self):
# 魔法方法:print(library) 显示图书馆概况
return f"📚 {self._name}:{len(self._books)}本藏书,{len(self._users)}位读者"
# ====== 运行演示 ======
# 创建图书馆
lib = Library("阳光社区图书馆")
# 添加图书(Book 和 EBook 混合,体现多态)
lib.add_book(Book("Python编程从入门到实践", "埃里克"))
lib.add_book(Book("深入理解计算机系统", "布莱恩特"))
lib.add_book(Book("活着", "余华"))
lib.add_book(EBook("人工智能简史", "尼克", "http://example.com/ai.pdf"))
lib.add_book(EBook("数据科学入门", "格拉斯", "http://example.com/ds.pdf"))
# 添加读者
lib.add_user(User("小明"))
lib.add_user(User("小红"))
# 用魔法方法展示信息
print(lib) # 📚 阳光社区图书馆:5本藏书,2位读者
print(f"藏书量:{len(lib)} 本") # 藏书量:5 本
lib.show_all_books() # 多态:Book 和 EBook 输出格式不同
# 借书还书操作
print("\n--- 借书操作 ---")
lib.borrow("小明", "Python编程从入门到实践")
lib.borrow("小明", "活着")
lib.borrow("小红", "人工智能简史")
lib.borrow("小红", "活着") # 已被小明借走
# 查看读者借阅情况
print("\n--- 读者借阅情况 ---")
for user in lib._users:
user.show_borrowed()
# 查看图书馆藏书状态(借出的会显示"已借出")
lib.show_all_books()
# 还书
print("\n--- 还书操作 ---")
lib.return_book("小明", "活着")
# 保存数据到文件
print("\n--- 保存数据 ---")
lib.save_to_file()
运行结果:
📚 阳光社区图书馆:5本藏书,2位读者
藏书量:5 本
📚 阳光社区图书馆 藏书列表(共 5 本):
《Python编程从入门到实践》- 作者:埃里克 [可借阅]
《深入理解计算机系统》- 作者:布莱恩特 [可借阅]
《活着》- 作者:余华 [可借阅]
《人工智能简史》- 作者:尼克 [电子书|可借阅]
《数据科学入门》- 作者:格拉斯 [电子书|可借阅]
--- 借书操作 ---
✅ 小明 成功借阅《Python编程从入门到实践》
✅ 小明 成功借阅《活着》
✅ 小红 成功借阅《人工智能简史》
❌ 《活着》已被借出
--- 读者借阅情况 ---
小明 借阅了 2 本:
《Python编程从入门到实践》- 作者:埃里克 [已借出]
《活着》- 作者:余华 [已借出]
小红 借阅了 1 本:
《人工智能简史》- 作者:尼克 [电子书|已借出]
📚 阳光社区图书馆 藏书列表(共 5 本):
《Python编程从入门到实践》- 作者:埃里克 [已借出]
《深入理解计算机系统》- 作者:布莱恩特 [可借阅]
《活着》- 作者:余华 [已借出]
《人工智能简史》- 作者:尼克 [电子书|已借出]
《数据科学入门》- 作者:格拉斯 [电子书|可借阅]
--- 还书操作 ---
✅ 小明 已归还《活着》
--- 保存数据 ---
✅ 数据已保存到 library_data.txt
分步拆解
1. Book 类(封装 + 魔法方法)
- 用
_title、_author、_borrowed私有属性封装数据,外部通过@property只读访问 __str__让print(book)输出友好格式:《书名》- 作者:xxx [可借阅]__repr__给开发者看:Book('书名', '作者')__eq__判断两本书是否相同:书名和作者都一样就视为同一本
2. EBook 类(继承 + 多态)
class EBook(Book)继承 Book,super().__init__()调用父类初始化- 新增
_url下载链接属性 - 重写
__str__,输出格式带[电子书|状态]标记——多态的体现:同样是print(book),Book和EBook输出不同
3. User 类(封装 + 魔法方法)
- 私有属性
_name和_borrowed_books(借阅列表) borrow_book()借书:检查是否已借出,未借出则借走并加入列表return_book()还书:检查是否在借阅列表中,在则归还并移除__str__输出读者信息,__len__返回借阅数量——len(user)就是借了几本书
4. Library 类(多态 + 文件读写)
show_all_books()遍历所有图书调用print(book)——多态,Book和EBook各自输出不同格式__len__返回藏书总数——len(lib)直接查看藏书量__str__输出图书馆概况——print(lib)一行展示图书馆信息save_to_file()将图书数据写入文本文件,用isinstance(book, EBook)区分类型load_from_file()从文件读取数据重建图书对象,try-except处理文件不存在的异常
5. 多态贯穿全局
print(book)对Book和EBook调用各自的__str__print(lib)调用Library的__str__len(lib)调用Library的__len__,len(user)调用User的__len__book in user._borrowed_books调用Book的__eq__判断是否同一本书
九、常见报错速查表
| 报错信息 | 出现场景 | 原因 | 解决方法 |
|---|---|---|---|
TypeError: unsupported operand type(s) for + |
obj1 + obj2 |
类中没有定义 __add__ |
在类中定义 __add__(self, other) 方法 |
TypeError: object of type 'XXX' has no len() |
len(obj) |
类中没有定义 __len__ |
在类中定义 __len__(self) 方法,返回整数 |
TypeError: __str__ returned non-string |
print(obj) |
__str__ 返回了非字符串类型 |
确保 __str__ 用 return 返回字符串 |
RecursionError: maximum recursion depth exceeded |
__eq__ 内部 |
__eq__ 中写 self == other 导致无限递归 |
改为直接比较属性:self.name == other.name |
AttributeError: 'NoneType' object has no attribute |
查询结果访问属性 | find_book() 返回 None 后直接 .title |
先判断 if book is not None 再访问属性 |
TypeError: unsupported operand type(s) for < |
obj1 < obj2 |
类中没有定义 __lt__ |
在类中定义 __lt__(self, other) 方法 |
十、本章小结
本章要点回顾
本章你掌握了面向对象的最后两块拼图——多态与魔法方法:
- 多态——不同对象调用同名方法表现出不同行为,Python 通过鸭子类型实现灵活的多态
__str__——让print(对象)输出友好信息,给用户看__repr__——让repr(对象)输出调试信息,给开发者看,列表中打印对象时也会用到__len__——让len(对象)返回自定义长度- 运算符重载——
__add__让对象支持+,__eq__让对象支持==,原理都是在类中定义对应魔法方法
至此,面向对象四大特性你已全部学完:封装(保护数据)、继承(复用代码)、多态(同一接口不同行为)、加上魔法方法(让对象像内置类型一样好用)。
往期回顾:
零基础学 Python 第1章 | 全平台装环境 + VS Code 配置 + 第一个 Hello World
零基础学 Python 第2章 | print 输出 + 变量赋值 + input 交互输入
零基础学 Python 第3章 | 条件判断:if / elif / else
零基础学 Python 第 4 章 | for 循环与 range():让程序帮你重复干活
零基础学 Python 第 5 章 | while 循环与循环嵌套:让程序看着条件自己干活
零基础学 Python 第 6 章 | 元组与集合:不可变数据与自动去重
零基础学 Python 第7章 | 字典 dict:键值对存储
零基础学 Python 第9章 | 函数基础:def、参数与返回值
零基础学 Python 第10章 | 函数进阶:参数灵活用法与作用域
零基础学 Python 第12章 | 文件读写:让数据持久保存
零基础学 Python 第13章 | 异常处理:try-except 让程序不崩溃
零基础学 Python 第15章 | 类与对象:面向对象编程入门
零基础学 Python 第17章 | 封装与 property:保护数据安全
全书学习路径回顾
恭喜你走到了这里!让我们回顾一下这 18 章走过的路:
第一阶段:基础语法(第1-4章)
从 print("Hello, World!") 开始,学会了变量与数据类型、运算符、if-else 条件判断、while 循环。这是你和 Python 的第一次握手。
第二阶段:数据容器(第5-8章)
学会了for 循环与列表、元组与集合、字典的键值对存储、字符串的切片与格式化。从此你有了组织和处理数据的工具箱。
第三阶段:函数与文件(第9-11章)
学会了函数定义与调用、文件读写、异常处理。你开始把代码组织成可复用的模块,程序不再是一长串平铺直叙的命令。
第四阶段:面向对象(第12-14章)
学会了类与对象的定义、继承的代码复用、封装的数据保护。你开始用"对象"的思维建模现实世界。
第五阶段:进阶与实战(第15-18章)
学会了多态与魔法方法,让你的对象像 Python 内置类型一样智能。最后的图书管理系统综合案例,把 18 章的知识融会贯通。
后续进阶方向
Python 的世界远不止这 18 章。掌握基础之后,你可以选择以下方向继续深入:
| 方向 | 简介 | 典型库 |
|---|---|---|
| 爬虫 | 自动抓取网页数据 | requests、BeautifulSoup、Scrapy |
| 数据分析 | 清洗、分析、可视化数据 | pandas、numpy、matplotlib |
| Web 开发 | 搭建网站和 API | Flask、Django、FastAPI |
| 人工智能 | 机器学习与深度学习 | scikit-learn、PyTorch、TensorFlow |
| 自动化办公 | 批量处理文件、表格、邮件 | openpyxl、python-docx、smtplib |
不管选哪个方向,这 18 章打下的基础都是通用的。变量、循环、函数、类——这些概念在任何 Python 项目中都会用到。
写在最后
学编程不是一蹴而就的事。你能坚持看完 18 章、跟着敲了那么多代码,已经比大多数人走得更远了。编程能力的提升靠的是"多写、多练、多思考",不要怕报错,每一个报错都是进步的机会。
把本章的图书管理系统拿来改造:加个图书分类、加个借阅历史记录、加个逾期提醒——每一次动手都是在加深理解。当你能独立扩展一个项目的时候,你就真的入门了。
感谢你选择这套教程,祝你在 Python 的路上越走越远。我们江湖再见!🚀
文末资源区
| 资源 | 说明 |
|---|---|
| Python 官方文档 - 魔法方法 | https://docs.python.org/3/reference/datamodel.html#special-method-names |
| Python 官方文档 - 运算符重载 | https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types |
| Python 官方文档 - 多态与鸭子类型 | https://docs.python.org/3/glossary.html#term-duck-typing |
| 本章完整源码 | chapter18_all.py(关注梅雅达编程笔记,评论领资料) |
每节课都配套课后练习题与完整源码。代码报错、看不懂知识点,可在评论区粘贴问题,逐一解答!
欢迎关注梅雅达编程笔记,持续分享Python零基础学习内容
更多推荐





所有评论(0)