Python迭代协议要求同时实现__iter__和__next__;仅__iter__返回自身却不定义__next__会导致next()报错,因可迭代对象与迭代器角色分离,__iter__必须返回含__next__的对象,__next__须状态可续且显式抛StopIteration。
Python 的迭代协议不是语法糖,而是明确由 __iter__ 和 __next__ 两个方法共同支撑的底层机制;只要实现了它们,对象就能被 for、list()、next() 等直接使用。
__iter__ 不够?常见误解是“只要返回一个可迭代对象就行”,但若 __iter__ 返回的是自身(即 self),而没定义 __next__,调用 next() 就会报 TypeError: 'X' object is not an iterator。因为「可迭代对象」和「迭代器」在协议中是两类角色:
__iter__ 的职责:返回一个迭代器(必须带 __next__)__next__ 的职责:返回下一个值,或抛出 StopIteration
__next__),但不能只做一半__iter__ 返回什么才合法?它必须返回一个实现了 __next__ 方法的对象 —— 可以是:
定义迭代器类)iter([1,2,3])、enumerate(...)、range(...)
yield)返回的 generator 对象,天然支持 __next__
错误写法示例(看似返回了列表,实则破坏协议):
def __iter__(self):
return [1, 2, 3] # ❌ 列表没有 __next__,不是迭代器正确写法之一(委托给内置迭代器):
def __iter__(self):
return iter(self._data) # ✅ iter() 返回真正的迭代器__next__ 怎么写才算合规?它必须满足两个硬性条件:有明确的终止信号,且每次调用状态可延续。典型结构是:
self._index)保存当前进度raise StopIteration
None 或静默退出,否则 for 循环会无限卡住示例(手动管理索引):
class Countdown:
def __init__(self, start):
self.start = start
def __iter__(self):
return self # 自身是迭代器
def __next__(self):
if self.start <= 0:
raise StopIteration
self.start -= 1
return self.start + 1注意:如果 __iter__ 返回的是新对象(比如每次 for 都新建一个迭代器),那 __next__ 就不该依赖外部可变状态,否则多个循环会互相干扰。
常见陷阱与调试建议
实际写的时候最容易漏掉的是状态隔离和异常边界:
__iter__ 应返回独立的迭代器(除非你明确要共享状态)__next__ 中不要用 print() 或日志干扰返回值逻辑for,务必手动调用 next(it) 多次,直到 StopIteration 被抛出__next__ 里做 IO 是合理的;但如果是内存列表,反复计算索引比缓存结果更慢协议本身很简单,但真正难的是让状态管理既安全又符合直觉 —— 尤其当对象既要被多次遍历,又要支持中途 break 或嵌套循环时。