应显式用 try/except stopiteration 捕获迭代器耗尽,而非依赖 next(it, default) 或错误地手动 raise stopiteration;for 循环自动处理但不提供结束状态信息。

直接用 try/except 捕获 StopIteration
Python 迭代器耗尽时抛出 StopIteration,这不是异常 bug,而是协议的一部分。想安全取值,必须显式捕获它——不能靠 if hasattr(it, '__next__') 之类猜测,也不该依赖 next(it, default) 就万事大吉。
常见错误是写成:
while True:
x = next(it) # 一旦耗尽,直接崩,没 catch
正确做法是:
- 用
try/except StopIteration:包裹next()调用 - 在
except块里做清理、退出循环或返回默认值 - 避免在 except 里再调
next()—— 那会重复抛错
next(it, default) 是最简方案,但有隐藏行为
这个内置函数本质就是 try/except 的语法糖,但它只帮你吞掉异常、返回默认值,不给你干预机会。适合“取一个值,没有就算了”的场景,比如解析配置项。
注意点:
- 如果
default是可变对象(如[]或{}),每次调用都返回同一个引用,可能引发意外共享 - 它无法区分“迭代器为空”和“
next()主动抛出StopIteration”(比如自定义迭代器里手动raise StopIteration) - 性能上比裸
next()+try略低,因为要构造异常对象再立即丢弃
自定义迭代器中不要手动 raise StopIteration 在 __next__ 外
PEP 479 已默认启用:在生成器(含 yield 的函数)的 __next__ 中,未被捕捉的 StopIteration 会被自动转为 RuntimeError。这是为了防止错误地把 StopIteration 当作普通异常层层往上抛。
所以:
- 在生成器函数里,直接
return或让函数自然结束即可,别写raise StopIteration - 在手动实现的类迭代器中,
__next__内可以raise StopIteration,但别在其他方法里抛它并期望被外层for捕获 - 如果真需要提前终止并传信息,改用自定义异常(如
class IterDone(Exception): pass),再由调用方显式处理
for 循环自动处理 StopIteration,但没法拿到“最后一批数据”
for x in it: 底层就是用 try/except StopIteration 实现的,你完全不用管。但这也意味着:一旦迭代结束,你无法知道是空迭代器、还是中途 break、还是正常走完。
如果业务需要区分这些情况(比如批量处理时想确认是否所有项都成功),得绕过 for,改用显式循环:
it = iter(data)
while True:
try:
x = next(it)
process(x)
except StopIteration:
print("迭代完成")
break
更关键的是:别指望 for 能帮你缓存最后一次 next() 的结果——它只负责消费,不保留状态。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











