Python 迭代器与可迭代对象详解
在 Python 开发中,「遍历」是最常见的操作之一——不管是扫列表、查字典键值对,还是逐行读文件,我们都习惯直接写 for ... in ...。但你有没有好奇过:为什么这些东西能放进 for 循环?为什么有些对象能被 next() 直接取元素? 这背后的核心,就是「可迭代对象(Iterable)」和「迭代器(Iterator)」。
可迭代对象 (Iterable)
简单来说,可迭代对象是“能被 for 循环遍历的对象”——它本身不直接产生“下一个值”的能力,但可以“变出”能产生值的工具。
Python 里常见的可迭代对象分两类:
- 基础集合类:
list、tuple、dict、set、str、bytes等 - 带延迟特性的类:生成器(generator)、文件对象、
zip()/map()/filter()的返回值等
怎么判断是不是可迭代?
用 isinstance() 配合 collections.abc.Iterable(注意要先导入标准库的抽象基类):
迭代器 (Iterator)
迭代器是可迭代对象的“进阶版”——它不仅能进 for 循环,还能被 next() 主动调用,直到耗尽抛出 StopIteration 异常,是真正“手握数据流控制权”的工具。
怎么判断是不是迭代器?
同样用 isinstance() + 抽象基类 collections.abc.Iterator:
可迭代转迭代器
用内置函数 iter() 就能一键转换:
迭代器 vs 可迭代对象:到底差在哪?
直接看文字可能绕,我们用对比表格+场景例子讲透:
举个最直观的无限自然数例子:
- 用列表写?不可能——
[0,1,2,...]写到内存爆炸也写不完 - 用迭代器写?分分钟搞定(后面讲自定义迭代器会实现)
再举个内存对比的小例子:
for 循环的“真面目”
你写的每一行 for x in xxx,Python 底层都会自动做这三件事:
- 调用
iter(xxx)拿到迭代器对象 - 循环调用
next(迭代器)赋值给x - 遇到
StopIteration就优雅退出
比如这段简单的代码:
Python 实际上在执行这段:
是不是突然觉得 for 循环没那么“神秘”了?
实用开发建议
1. 处理大数据/无限序列,首选迭代器/生成器
如果要处理几百万、几千万行的文件,或者遍历无限序列,别用列表推导式,用生成器表达式或者迭代器类——不然内存会被撑爆。
2. 自定义迭代器,只需要两个方法
如果要自己写迭代器类(比如实现刚才的无限自然数),必须实现:
__iter__():必须返回自己(self),这是迭代器和可迭代对象的核心接口统一__next__():实现“取元素、推进指针、抛异常”的逻辑
直接上代码:
如果要做有终止条件的自定义迭代器,加个判断抛 StopIteration 就行:
3. 迭代器是“一次性”的!
这个点非常容易踩坑!迭代器遍历完一次就“空”了,再用 next() 或者 for 循环都不会有值:
总结
理解迭代器和可迭代对象,是写高效、Pythonic、内存友好代码的基础:
- 可迭代对象是“容器/原料”,能提供迭代器
- 迭代器是“工具/工人”,手握惰性计算的逻辑
for循环只是迭代器的语法糖- 自定义迭代器要实现
__iter__(返回自己)和__next__
下次再写遍历的时候,不妨停下来想想:这里用列表还是生成器/迭代器更合适?

