1. 迭代器是什么? #
- 迭代器(iterator) 是一种按序逐个产出元素的对象,采用惰性求值。
- 需要下一个元素时才计算,不会先把全部数据装进内存。
- Python 的
for 循环底层正是:对可迭代对象调用 iter() 得到迭代器,再反复 next() 取元素,直到抛出 StopIteration 结束循环。
- 初学不必手写迭代器,但理解这套机制有助于:逐行读大日志、数据库大批量游标、生成器表达式。
- 也有助于避免「把百万条记录
list() 进内存」的坑。
2. 可迭代对象 vs 迭代器 #
- 两个概念容易混用,区别要记清。
- 可迭代对象(Iterable) 能被
for 遍历,实现了 __iter__(),返回一个迭代器。
- 迭代器(Iterator) 除了
__iter__(),还有 __next__(),负责「拿出下一个值」。
- 列表、字典、字符串、文件对象都是可迭代对象,本身通常不是迭代器。
- 对它们调用
iter(obj) 才得到迭代器。
- 迭代器用完即尽:同一迭代器只能完整走一遍,再走需重新
iter(...) 或新建列表等对象。
| 概念 |
说明 |
例子 |
| 可迭代对象 (Iterable) |
能被 for 遍历,有 __iter__() |
list、dict、str、文件对象 |
| 迭代器 (Iterator) |
有 __iter__() 和 __next__(),负责「一个个取」 |
iter([1,2,3]) |
nums = [1, 2, 3]
it = iter(nums)
print(next(it))
print(next(it))
3. 迭代器协议 #
- 要让自定义类支持
for 循环,需实现迭代器协议。
__iter__() 返回迭代器自身(或另一个迭代器对象)。
__next__() 返回下一个元素,没有更多元素时 raise StopIteration。
- 自定义迭代器多用于:按规则生成序列、封装外部 API 的分页拉取、或教学演示。
- 日常处理列表、文件、查询结果时,用内置可迭代对象就够了。
4. iter() 与 next() #
iter(可迭代对象) 获取迭代器;next(迭代器) 手动取下一个元素,耗尽时抛 StopIteration。
- 传
next(it, default) 可在结束时返回默认值而不抛异常。
- 多数场景用
for 即可,不必手写 next。
- 需要手动步进、对接只认迭代器的 API、或调试「取了几个元素」时才会直接用到这一对函数。
data = ["a", "b", "c"]
it = iter(data)
print(next(it))
print(next(it))
print(next(it))
print(next(it, "没了"))
5. 项目中的典型场景 #
- 全栈项目里与迭代器最相关的两类实践:大文件逐行读(控制内存)、认清一次遍历与多次遍历的区别(迭代器耗尽后不能重来)。
- ORM 大批量导出、日志分析、CSV 处理都适用同一思路:能流式就流式,避免一次性
readlines() 或 .all()。
5.1 逐行读大文件 #
- 打开的文件对象是可迭代的,
for line in f 按行惰性读取,不会把整个文件读进列表。
- 几百万行日志若
f.readlines() 可能占满内存,生产环境应逐行处理或分批。
with open("access.log", "r", encoding="utf-8") as f:
for line in f:
print(line)
5.2 一次遍历 vs 多次遍历 #
- 列表可
for 多遍;迭代器 / 生成器消费一次后内部状态已耗尽,再次 list(it) 往往为空。
- 需要重复遍历时:转成列表(确认数据量可接受)、重新
iter(可迭代对象),或重新执行查询。
it = iter([1, 2, 3])
print(list(it))
print(list(it))
6. 项目开发要点 #
- 迭代器不是每天都要写的 API,但影响内存与性能的选择。
for 依赖可迭代对象;大数据优先迭代器/生成器,避免 list(海量查询)。
- 文件、日志、导出 CSV 用逐行迭代,控制内存。
- ORM 大批量处理 用
iterator() 或游标,不要默认 .all() 全进内存。
- 迭代器只能消费一次;要重复用就转成列表(确认数据量可接受)或重新创建。