本章摘要

  1. 核心目标:掌握多态与魔法方法,让自定义对象支持print输出、len()统计和运算符操作
  2. 核心知识点:多态概念与实现、__str____repr____len____add__运算符重载、__eq__比较重载
  3. 实操产出:迷你图书管理系统,综合运用类定义、继承、封装、多态、魔法方法、文件读写
  4. 前置基础:第17章封装、第16章继承、第15章类与对象

一、写在前面

上一章学了封装,你学会了用私有属性和 @property 保护数据,让对象像一个"黑盒子"——外面只能通过规定的方法操作,不能乱改内部状态。封装让代码更安全、更规范。

但你可能发现两个问题:第一,print(对象) 输出的结果是一串看不懂的内存地址 <__main__.Student object at 0x7f...>,一点也不友好;第二,两个对象相加 obj1 + obj2 直接报错,比较相等 obj1 == obj2 比的也是内存地址,不是我们想要的内容。

这两个问题的根源是一样的:Python 不知道你的对象该怎么打印、怎么相加、怎么比较。魔法方法(Magic Methods)就是来解决这些问题的——你只需要在类里定义几个特殊方法,Python 就会自动调用它们,让你的对象像内置类型一样好用。

📷 图片占位:magic-methods-overview.png — 常用魔法方法速查表(__str__、__repr__、__len__、__add__、__eq__ 等)

本章还会讲到面向对象的最后一个特性——多态。多态和魔法方法其实是"一体两面":魔法方法本身就是多态的体现,print() 对不同对象调用各自的 __str__(),输出完全不同的结果。


二、多态:同名方法,不同行为

2.1 什么是多态

多态一句话概括:不同的对象调用同名方法,表现出不同的行为

📷 图片占位:polymorphism-concept.png — 多态概念图(不同对象调用同名方法产生不同行为)

举个例子:你喊"叫一声",狗会"汪汪汪",猫会"喵喵喵",鸭子会"嘎嘎嘎"。同样是 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())  # 嘀嘀嘀,我是机器人

运行结果:

汪汪汪!
嘀嘀嘀,我是机器人

DogRobot 没有继承关系,但都有 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)BookEBook 输出不同

3. User 类(封装 + 魔法方法)

  • 私有属性 _name_borrowed_books(借阅列表)
  • borrow_book() 借书:检查是否已借出,未借出则借走并加入列表
  • return_book() 还书:检查是否在借阅列表中,在则归还并移除
  • __str__ 输出读者信息,__len__ 返回借阅数量——len(user) 就是借了几本书

4. Library 类(多态 + 文件读写)

  • show_all_books() 遍历所有图书调用 print(book)——多态,BookEBook 各自输出不同格式
  • __len__ 返回藏书总数——len(lib) 直接查看藏书量
  • __str__ 输出图书馆概况——print(lib) 一行展示图书馆信息
  • save_to_file() 将图书数据写入文本文件,用 isinstance(book, EBook) 区分类型
  • load_from_file() 从文件读取数据重建图书对象,try-except 处理文件不存在的异常

5. 多态贯穿全局

  • print(book)BookEBook 调用各自的 __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) 方法

十、本章小结

本章要点回顾

本章你掌握了面向对象的最后两块拼图——多态与魔法方法:

  1. 多态——不同对象调用同名方法表现出不同行为,Python 通过鸭子类型实现灵活的多态
  2. __str__——让 print(对象) 输出友好信息,给用户看
  3. __repr__——让 repr(对象) 输出调试信息,给开发者看,列表中打印对象时也会用到
  4. __len__——让 len(对象) 返回自定义长度
  5. 运算符重载——__add__ 让对象支持 +__eq__ 让对象支持 ==,原理都是在类中定义对应魔法方法

至此,面向对象四大特性你已全部学完:封装(保护数据)、继承(复用代码)、多态(同一接口不同行为)、加上魔法方法(让对象像内置类型一样好用)。

往期回顾:

《Python 零基础入门:从积木到代码》专栏序

零基础学 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 第8章 | 字符串操作与格式化输出

零基础学 Python 第9章 | 函数基础:def、参数与返回值

零基础学 Python 第10章 | 函数进阶:参数灵活用法与作用域

零基础学 Python 第11章 | 匿名函数与高阶函数

零基础学 Python 第12章 | 文件读写:让数据持久保存

零基础学 Python 第13章 | 异常处理:try-except 让程序不崩溃

零基础学 Python 第14章 | 模块、包与第三方库

零基础学 Python 第15章 | 类与对象:面向对象编程入门

零基础学 Python 第16章 | 继承与方法重写

零基础学 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 章。掌握基础之后,你可以选择以下方向继续深入:

方向 简介 典型库
爬虫 自动抓取网页数据 requestsBeautifulSoupScrapy
数据分析 清洗、分析、可视化数据 pandasnumpymatplotlib
Web 开发 搭建网站和 API FlaskDjangoFastAPI
人工智能 机器学习与深度学习 scikit-learnPyTorchTensorFlow
自动化办公 批量处理文件、表格、邮件 openpyxlpython-docxsmtplib

不管选哪个方向,这 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零基础学习内容

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐