人人都会AI编程

迭代协议、可迭代对象、迭代器原理

更新时间:2026-07-12

Python 中 for 循环能够遍历列表、字符串、文件等各种对象,不是因为解释器给每种类型写了特例,而是因为这背后有一个统一的机制——迭代协议。理解这个协议,你就能看懂 for 到底在做什么,也能自己写出可迭代的自定义对象。


迭代协议

迭代协议是 Python 为“可被遍历”的对象约定的一套接口规则,由两个核心方法组成:

  1. iter():返回一个迭代器对象。
  2. next():返回迭代器当前的值,并将内部指针移到下一个元素;如果没有元素了,则抛出 StopIteration 异常。

任何实现了 iter 方法的对象都是可迭代对象(iterable)
任何同时实现了 iternext 方法的对象就是迭代器(iterator)

换句话说,可迭代对象是“能给你迭代器”的东西,而迭代器是“真正执行逐个取值任务”的东西。


可迭代对象

  • 定义:实现了 iter 方法,调用该方法会返回一个迭代器。
  • 常见例子:列表、元组、字符串、字典、集合、文件对象、range() 对象等都属于可迭代对象。
  • 关键点:可迭代对象本身不一定是迭代器,它只是可被迭代。每次对它调用 iter()(本质上调用 iter)都会得到一个新的迭代器,从起始位置重新开始遍历。

实际验证:

lst = [1, 2, 3]
print(hasattr(lst, '__iter__'))   # True —— 可迭代对象
print(hasattr(lst, '__next__'))   # False —— 不是迭代器

迭代器

  • 定义:同时实现了 iternext 的对象。其中 iter 通常返回 self(即迭代器本身就是可迭代的),next 负责依次返回元素并在结束时抛出 StopIteration
  • 特点
  • 惰性求值:只在需要时才产生下一个值,不预先在内存中存储所有数据,这对于处理大文件或无限序列非常有价值。
  • 单向消费:一旦用 next() 取走一个值,就不能回头再取同一个值,除非重新获取一个新的迭代器。
  • 获取迭代器的方式
  • 对可迭代对象使用内置函数 iter()
  • for 循环中,Python 自动帮你调用 iter() 获取迭代器,然后不断调用 next(),直到捕获 StopIteration

示例:手动使用迭代器

s = "abc"
it = iter(s)           # 获取迭代器
print(next(it))        # 'a'
print(next(it))        # 'b'
print(next(it))        # 'c'
# next(it)             # StopIteration

for 循环的内部原理

平常我们写的:

for item in [1,2,3]:
    print(item)

实际上等价于:

iterable = [1,2,3]
iterator = iter(iterable)    # 调用 __iter__
while True:
    try:
        item = next(iterator)  # 调用 __next__
    except StopIteration:
        break
    print(item)

因此,任何满足迭代协议的对象都可以直接被 for 循环使用,这也意味着你可以在自定义类中实现 iternext,让实例变得“可遍历”。


实际应用价值

  1. 处理大文件:直接对文件对象迭代 for line in file,按行读取而不是一次性全部载入内存。
  2. 生成无限序列:使用迭代器可以表示“所有偶数”这种理论上的无限集合,结合 next() 逐步取值,不会撑爆内存。
  3. 自定义可迭代类:当你设计一个代表数据库查询结果的数据结构时,实现迭代协议后,用户就能直接用 for row in query_result 的方式遍历,使用体验和标准类型完全一致。

理解迭代协议,你就从“会用 for 循环”进阶到了“可以为任意对象设计遍历方式”的水平,这也是 Python 灵活性和统一性的重要基石。