当前位置:首页>python>【一起学 Python】第 65 天:并发与迭代启航:迭代器协议深度解析

【一起学 Python】第 65 天:并发与迭代启航:迭代器协议深度解析

  • 2026-09-02 19:01:42
【一起学 Python】第 65 天:并发与迭代启航:迭代器协议深度解析

欢迎来到 Python 学习计划的第 65 天!🎉

恭喜你完成了 异常与文件模块(第 57-64 天)!从今天开始,我们将进入 进阶阶段第三模块:并发与迭代(第 65-69 天)。

这是 Python 高级特性的核心领域。今天我们要学习的是整个迭代体系的基石——迭代器协议(Iterator Protocol)。理解它,你才能明白 for 循环的本质,并为明天学习生成器(Generator)和异步编程(Asyncio)打下坚实基础!

一、什么是迭代器协议?

1. 核心定义

迭代器协议 是 Python 中用于实现迭代对象的一套标准规则。任何对象只要实现了 __iter__() 和 __next__() 方法,就可以成为迭代器。

2. 可迭代对象 vs 迭代器

这是初学者最容易混淆的概念。

特性

可迭代对象 (Iterable)

迭代器 (Iterator)

定义

实现 __iter__ 方法

实现 __iter__ 和 __next__

用途

可以被迭代(如 for)

实际执行迭代过程

示例

list, tuple, str, dict

iter(list), 文件对象

状态

无状态

有状态(记住当前位置)

复用

可多次迭代

只能迭代一次

from collections.abc import Iterable, Iteratornumbers = [1, 2, 3]# 列表是可迭代对象print(isinstance(numbers, Iterable))  # Trueprint(isinstance(numbers, Iterator))  # False# 创建迭代器iterator = iter(numbers)print(isinstance(iterator, Iterator))  # True
💡 关键点:可迭代对象是"数据源",迭代器是"读取指针"。

二、协议核心方法

1. __iter__() 方法

返回迭代器对象本身。这使得迭代器本身也是可迭代的。

class MyIterator:    def __iter__(self):        return self  # 必须返回 self

2. __next__() 方法

返回下一个元素。如果没有更多元素,必须抛出 StopIteration 异常。

    def __next__(self):        if self.current >= self.end:            raise StopIteration  # 告诉循环结束了        value = self.current        self.current += 1        return value

3. 内置函数支持

  • iter(obj): 调用 obj.__iter__()。
  • next(obj): 调用 obj.__next__()。
iterator = iter([1, 2, 3])print(next(iterator))  # 1print(next(iterator))  # 2print(next(iterator, "默认值"))  # 3 (带默认值避免异常)

三、for 循环的工作原理

for 循环是迭代器协议的语法糖。以下两段代码等价:

# 语法糖:for 循环for item in [1, 2, 3]:    print(item)# 底层实现:while 循环iterator = iter([1, 2, 3])while True:    try:        item = next(iterator)        print(item)    except StopIteration:        break
💡 理解:for 循环自动处理了 iter() 创建迭代器和 StopIteration 异常捕获。

四、自定义迭代器(OOP 实战)

结合之前学过的 类与对象(参考 [File 67](67-实例方法与 self 的本质.md)),我们可以创建自己的迭代器。

1. 基础示例:计数器

class Counter:    def __init__(self, start, end):        self.current = start        self.end = end    def __iter__(self):        return self    def __next__(self):        if self.current >= self.end:            raise StopIteration        value = self.current        self.current += 1        return value# 使用counter = Counter(1, 5)for num in counter:    print(num)  # 1, 2, 3, 4

2. 进阶示例:反向迭代器

class Reverse:    """反向迭代序列"""    def __init__(self, data):        self.data = data        self.index = len(data)    def __iter__(self):        return self    def __next__(self):        if self.index == 0:            raise StopIteration        self.index -= 1        return self.data[self.index]# 使用for char in Reverse("Python"):    print(char)  # n, o, h, t, y, P

3. 最佳实践:分离可迭代对象与迭代器

为了支持多次迭代,应该分离设计。

class NumberRange:    """可迭代对象(可多次迭代)"""    def __init__(self, start, end):        self.start = start        self.end = end    def __iter__(self):        return NumberRangeIterator(self.start, self.end)class NumberRangeIterator:    """迭代器(一次性消费)"""    def __init__(self, start, end):        self.current = start        self.end = end    def __iter__(self):        return self    def __next__(self):        if self.current >= self.end:            raise StopIteration        value = self.current        self.current += 1        return value# 使用numbers = NumberRange(1, 4)print(list(numbers))  # [1, 2, 3]print(list(numbers))  # [1, 2, 3] (可以再次迭代)

五、内置迭代器工具

1. iter() 带哨兵值

可以创建一个迭代器,直到遇到特定值停止。

import randomdef roll_dice():    return random.randint(1, 6)# 一直掷骰子直到掷出 6for roll in iter(roll_dice, 6):    print(f"掷出:{roll}")

2. 文件对象是迭代器

文件对象天然支持迭代器协议,逐行读取。

with open("data.txt", "r", encoding="utf-8") as f:    for line in f:  # 等价于 next(f)        print(line.strip())

六、类型提示支持(结合进阶模块)

from collections.abc import Iterator, Iterabledef process_data(data: Iterable[int]) -> Iterator[int]:    """处理可迭代数据,返回迭代器"""    return (x * 2 for x in data)def consume(iterator: Iterator[str]) -> None:    """消费迭代器"""    for item in iterator:        print(item)

七、常见误区与注意事项

1. 迭代器只能使用一次

迭代器是"一次性消耗品",用完即废。

iterator = iter([1, 2, 3])print(list(iterator))  # [1, 2, 3]print(list(iterator))  # [] (已耗尽)

2. 忘记返回 self

__iter__ 必须返回迭代器对象本身(通常是 self)。

# ❌ 错误def __iter__(self):    pass  # 返回 None# ✅ 正确def __iter__(self):    return self

3. 忘记抛出 StopIteration

如果不抛出,循环将永远不会停止(无限循环)。

# ❌ 错误def __next__(self):    return self.current  # 没有终止条件# ✅ 正确def __next__(self):    if self.current >= self.end:        raise StopIteration    return self.current

4. 无法随机访问

迭代器只能顺序访问,不支持索引。

iterator = iter([1, 2, 3])
# print(iterator[1])  # ❌ TypeError

八、总结

知识点

说明

Iterable

实现 __iter__,可多次迭代(如 list)

Iterator

实现 __iter__ + __next__,一次性消费

__iter__

返回迭代器本身

__next__

返回下一个值,结束抛 StopIteration

for 原理

自动调用 iter() 和 next() 捕获异常

类型提示

Iterable[T], Iterator[T]

最佳实践

大数据用迭代器,需随机访问用列表

核心要点

  1. 迭代器协议是 Python 迭代的基石,for 循环基于此实现。
  2. 迭代器是一次性的,耗尽后需重新创建。
  3. 自定义迭代器需实现两个方法,并注意终止条件。
  4. 分离可迭代对象与迭代器 可支持多次迭代。
  5. 文件对象天然支持迭代,逐行读取最省内存。

📌 明日预告:生成器函数与 yield 关键字

明天我们将进入 并发与迭代模块第二天!

  • 主题:生成器函数与 yield 关键字
  • 核心问题:
    1. 生成器与普通函数有什么区别?
    2. yield 关键字的作用是什么?
    3. 生成器表达式怎么写?
    4. send(), throw(), close() 方法怎么用?
    5. 生成器如何实现协程?

💡 提前思考:

  1. 如果不想写 __iter__ 和 __next__,有没有更简单的方法创建迭代器?
  2. yield 和 return 有什么区别?
  3. 生成器为什么能节省内存?

掌握迭代器协议,是理解 Python 高效迭代的关键!明天学习更简洁的生成器!继续加油!🚀

最新文章

随机文章