Python迭代器核心是iter()、next()及__iter__()/__next__()方法;for循环依赖对象是否实现这些协议;生成器函数通过yield返回可迭代的generator对象,其状态保存在帧对象中。

Python 里没有“迭代器系统学习路线第568讲”这种官方概念——iter()、next()、__iter__() 和 __next__() 就是全部核心,其余全是围绕它们的封装或语法糖。
为什么 for 循环能遍历列表但不能直接遍历整数
因为 for 内部会自动调用 iter(obj),而该函数只对实现了 __iter__() 方法或支持序列协议(有 __getitem__ 且索引从 0 开始)的对象成功返回迭代器。整数没这两个方法,调用 iter(42) 直接抛 TypeError: 'int' object is not iterable。
常见误操作:
- 把自定义类的
__iter__写成返回self却漏了__next__→ 报TypeError: iter() returned non-iterator - 在
__next__里忘了抛StopIteration→for死循环
yield 是怎么让函数变成迭代器的
含 yield 的函数不是普通函数,而是生成器函数;调用它不执行逻辑,只返回一个 generator 对象——它既是迭代器(有 __iter__ 和 __next__),也是可迭代对象(能被 for 消费)。
立即学习“Python免费学习笔记(深入)”;
关键点:
-
generator的状态保存在帧对象(frame)里,每次next()恢复执行到上次yield处 -
return在生成器中等价于抛StopIteration,其返回值可通过exc.value捕获(需用try/except StopIteration as exc) - 生成器一旦耗尽,再调
next()必报StopIteration,不可重用
def countdown(n):
while n > 0:
yield n
n -= 1
return "done"
g = countdown(2)
print(next(g)) # 2
print(next(g)) # 1
try:
next(g)
except StopIteration as e:
print(e.value) # done
手动实现一个带缓冲的文件行迭代器
标准 open() 返回的文件对象是迭代器,但它是逐行读取、无缓冲的;若想预读几行做判断(比如跳过注释、合并续行),就得自己控制 next() 调用节奏。
典型陷阱:
- 在
__next__中调file.readline()后不检查空字符串 → 遇到空行就提前终止 - 用
list(file)一次性读完,失去流式处理优势 - 忘记在
__del__或close()中关闭文件 → 句柄泄漏
class BufferedLineIter:
def __init__(self, path):
self.file = open(path, 'r', encoding='utf-8')
self._buffer = []
def __iter__(self):
return self
def __next__(self):
if self._buffer:
return self._buffer.pop(0)
line = self.file.readline()
if not line:
self.file.close()
raise StopIteration
return line.rstrip('\n')
def peek(self, n=1):
while len(self._buffer) < n:
line = self.file.readline()
if not line:
break
self._buffer.append(line.rstrip('\n'))
return self._buffer[:n]真正难的不是写迭代器,而是判断什么时候该用迭代器、什么时候该用生成器表达式、什么时候干脆用列表推导式——这取决于你是否需要延迟计算、是否要多次遍历、内存是否敏感。别被“第568讲”吓住,翻源码看 itertools 里几个函数的实现,比追教程快得多。










