1. 迭代协议是什么? #
- 迭代协议(iteration protocol) 是 Python 约定的一套双方法机制,规定对象如何被
for、list()、sum() 等消费。
- 可迭代对象实现
__iter__(),返回一个迭代器。
- 迭代器再实现
__next__(),每次返回下一个元素。
- 没有更多元素时
raise StopIteration,for 据此结束循环。
- 搞清这层关系,能读懂「为什么生成器省内存」「为什么迭代器只能走一遍」。
- 也能在读 Django QuerySet、文件对象、框架源码时少踩坑。
- 日常写业务不必手写协议,但知道
for 底层在做什么,有助于选对列表还是生成器。
2. 核心关系 #
- 迭代相关概念呈层层包含:列表、字典等是可迭代对象。
- 对它们
iter() 得到迭代器。
- 生成器(
yield / 生成器表达式)是一种由解释器自动实现协议的迭代器。
- 下图与示意帮助建立整体图景,再对照下表记关键方法与特点。

可迭代对象 (Iterable) 有 __iter__(),可被 for 遍历
↓ iter() 得到
迭代器 (Iterator) 有 __iter__() + __next__(),逐个产出
↓
生成器 (Generator) 由 yield / (x for x in ...) 自动实现协议
| 概念 |
关键方法 |
特点 |
| 可迭代对象 |
__iter__() 返回迭代器 |
列表、字典、文件;可多次 for |
| 迭代器 |
__iter__ + __next__ |
记住位置;用完即止 |
| 生成器 |
自动实现上述方法 |
项目里最常用的迭代器 |
3. for 循环在做什么? #
- 写法
for x in items 时,Python 并不魔法地「遍历列表下标」。
- 而是:先
iterator = iter(items),再循环里 x = next(iterator),捕获 StopIteration 后跳出。
- 下面用
while + try/except 手动模拟这一过程,便于与协议方法对应。
- 日常仍直接写
for 即可,调试或读 CPython 相关源码时可对照此流程。
items = [1, 2, 3]
iterator = iter(items)
while True:
try:
x = next(iterator)
except StopIteration:
break
print(x)
4. 可迭代对象 vs 迭代器 #
- 列表、字典、字符串等容器是可迭代对象,通常不是迭代器。
- 可对同一列表
for 多遍,每次 for 会新建迭代器。
iter(lst) 返回的才是迭代器,负责记住「取到哪了」。
- 标准库
collections.abc 提供 Iterable、Iterator 抽象基类,可用 isinstance 做类型判断。
- 读第三方库文档时常见「参数类型为 Iterable」。
from collections.abc import Iterable, Iterator
lst = [1, 2, 3]
it = iter(lst)
print(isinstance(lst, Iterable))
print(isinstance(lst, Iterator))
print(isinstance(it, Iterator))
|
列表等容器 |
iter(列表)、生成器 |
多次 for |
可以 |
生成器/迭代器通常不行,需重建 |
| 角色 |
数据源 |
实际「一个个取」的对象 |
5. 生成器与协议 #
- 生成器是项目里最常用的迭代器实现方式。
- 函数里写
yield,或写 生成器表达式 (x for x in data),解释器会自动生成 __iter__ / __next__,无需手写状态机。
- 因此「会用
yield」就等于「满足迭代协议」。
- 可交给任何接受可迭代对象的 API(
for、list、sum 等)。
def gen():
yield 1
yield 2
g = gen()
print(next(g))
print(next(g))
yield 与生成器表达式的详细用法见推导式、生成器章节。
6. 自定义可迭代 #
- 仅当自定义类需要被
for 遍历时,才实现 __iter__()(返回迭代器,可以是 self 或其它对象)。
- 也可同时实现
__next__() 让类自身当迭代器(如下例)。
- 普通 CRUD、接口开发几乎不必手写;读 ORM、SDK 源码或写小型工具类时可能遇到。
- 更简单的方式往往是:用
yield 包一层生成器函数,而不是手写 __next__ 里的 index 自增。
class MyIterable:
def __init__(self, data):
self.data = data
def __iter__(self):
self.index = 0
return self
def __next__(self):
if self.index < len(self.data):
val = self.data[self.index]
self.index += 1
return val
else:
raise StopIteration
my_iterable = MyIterable([1, 2, 3, 4])
for item in my_iterable:
print(item)
7. 项目开发要点 #
- 迭代协议偏原理与选型,不阻碍日常写
for。
for 只要求可迭代,不要求你理解协议才能写业务。
- 大数据用生成器/迭代器,不要先
list(全表)。
- 迭代器一次性消费:
StopIteration 后需重新 iter() 或重新调用生成器函数。
- 实现自定义遍历:用
yield 包一层,少写 __next__ 状态机。
- 判断类型:第三方库文档写「接受 Iterable」时,列表、生成器、文件对象都可传。
8. 总结 #
- 迭代协议把
__iter__ → __next__ → StopIteration 串成 for 的底层逻辑。
- 生成器用
yield 自动满足协议。
- 记住可迭代 vs 迭代器 vs 生成器的包含关系即可应对多数场景。
- 下表速查关键符号。
| 方法 / 异常 |
作用 |
__iter__() |
返回迭代器,供 for 使用 |
__next__() |
返回下一项 |
StopIteration |
没有更多元素时结束迭代 |
yield |
自动生成生成器,满足迭代协议 |