迭代器

3 阅读4分钟

Python 迭代器(Iterator)

迭代器是 Python 中支持惰性遍历的核心机制。简单来说,它是一个可以记住遍历位置的对象,每次调用 next() 就返回下一个值,直到没有更多元素时抛出 StopIteration 异常。

1. 迭代器协议

一个对象要成为迭代器,必须实现两个方法:

  • __iter__():返回迭代器对象自身(通常就是 self)。
  • __next__():返回下一个可用元素;如果没有元素了,必须抛出 StopIteration
class MyIterator:
    def __init__(self, limit):
        self.limit = limit
        self.current = 0

    def __iter__(self):
        return self          # 迭代器返回自身

    def __next__(self):
        if self.current < self.limit:
            value = self.current
            self.current += 1
            return value
        else:
            raise StopIteration

it = MyIterator(3)
print(next(it))  # 0
print(next(it))  # 1
print(next(it))  # 2
# print(next(it))  # StopIteration

2. 可迭代对象 vs 迭代器

概念特点示例
可迭代对象 (Iterable)实现了 __iter__() 方法,能返回一个迭代器list, str, tuple, dict, set, 文件对象
迭代器 (Iterator)实现了 __iter__()__next__() 方法generator 对象, enumerate 对象, zip 对象, 自定义迭代器

关系:可迭代对象不一定是迭代器,但迭代器一定是可迭代对象(因为它有 __iter__)。

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

it = iter(lst)                    # 从列表获取迭代器
print(hasattr(it, '__iter__'))    # True
print(hasattr(it, '__next__'))    # True → 是迭代器

3. for 循环背后的迭代器

for x in iterable: 的本质是:

  1. 调用 iter(iterable) 获取一个迭代器。
  2. 反复调用 next(迭代器) 将返回值赋给 x
  3. 捕获 StopIteration 并退出循环。
# 等价于
it = iter([1, 2, 3])
while True:
    try:
        x = next(it)
        print(x)
    except StopIteration:
        break

4. 生成器:最方便的迭代器

生成器(使用 yield 的函数或生成器表达式)自动实现迭代器协议,不需要手动编写 __iter____next__

def gen(n):
    for i in range(n):
        yield i

g = gen(3)
print(next(g))  # 0
print(next(g))  # 1
print(next(g))  # 2
# print(next(g))  # StopIteration

生成器是迭代器的子类型,因此可以用于任何需要迭代器的地方。

5. 迭代器的特性

  • 惰性求值:只在需要时计算下一个值,节省内存。
  • 单向:只能向前,不能重置或后退。
  • 一次性:遍历完毕后,无法再次使用(除非重新创建)。
  • 内置支持next()iter() 函数,以及 forlist()sum() 等都会自动使用迭代器。

6. 常见内置迭代器

  • enumerate(iterable) → 返回 (索引, 元素) 的迭代器。
  • zip(iter1, iter2) → 并行聚合多个迭代器的迭代器。
  • reversed(sequence) → 反向遍历的迭代器。
  • map(func, iterable) → 应用函数结果的迭代器。
  • filter(pred, iterable) → 筛选元素的迭代器。

7. 手动控制迭代器

使用 next() 手动推进:

fruits = ['apple', 'banana', 'cherry']
it = iter(fruits)
print(next(it))          # apple
print(next(it))          # banana
print(list(it))          # ['cherry']  注意:剩余元素被消费

8. 总结

你需要知道的关键点
迭代器是实现了 __next__()__iter__() 的对象
可迭代对象通过 iter() 产生迭代器
for 循环底层完全依赖迭代器
生成器是最简单的迭代器创建方式
迭代器是惰性、单向、一次性

理解迭代器后,你会更清楚 Python 如何高效处理大数据流、文件读取、无限序列等场景。 是的,你的理解基本正确。for 循环在执行时,会按照迭代器协议自动完成以下步骤:

  1. 检查目标是否可迭代:通过调用内置函数 iter(目标),这要求目标对象实现了 __iter__() 方法。如果没实现,iter() 会抛出 TypeError: '...' object is not iterable

  2. 获取迭代器iter(目标) 返回一个迭代器对象(这个对象必须实现了 __next__() 方法)。

  3. 反复调用 next()for 循环内部不断调用 next(迭代器),每次拿到返回值赋给循环变量,直到 next() 抛出 StopIteration 异常,循环结束。

所以,for 循环的完整判断逻辑是:

  • 目标是否可迭代 → 即是否有 __iter__ 方法(或 __getitem__ 作为后备,但现代 Python 主要依赖 __iter__)。
  • 迭代器是否有 __next__ → 否则 next() 调用会失败。

你提到的“对应的迭代器中有 next 函数”正是第 3 步能正常工作的前提。

验证示例

# 一个没有 __iter__ 的类
class NotIterable:
    pass

obj = NotIterable()
for x in obj:   # TypeError: 'NotIterable' object is not iterable
    pass

# 一个有 __iter__ 但返回的对象没有 __next__
class BadIterable:
    def __iter__(self):
        return 123   # 返回的不是迭代器(没有 __next__)

obj2 = BadIterable()
for x in obj2:   # TypeError: iter() returned non-iterator of type 'int'
    pass

因此,for 循环隐式但严格地依赖这两个方法的存在。你的表述“先判断目标是否是可迭代对象,且目标中有 iter 函数,且对应的迭代器中有 next 函数”基本准确,只是更精确地说:for 会先调用 iter() 来触发检查,然后要求返回的对象支持 next()