LoveLearn

Python3 迭代器与生成器详解

⏱️ 5 分钟

Python3 迭代器与生成器详解

在 Python 中,迭代器(Iterator)生成器(Generator) 是非常重要的概念。
它们不仅让代码更优雅,还能显著降低内存占用,是理解 Python “惰性计算”思想的关键。

本文将从以下几个方面展开:

  • 什么是可迭代对象
  • 迭代器的工作原理
  • 生成器的两种写法
  • 迭代器 vs 生成器
  • 实战示例与常见陷阱

一、什么是可迭代对象(Iterable)

可迭代对象

只要能被 for 循环遍历的对象,就是可迭代对象。

常见的可迭代对象:

  • list
  • tuple
  • dict
  • set
  • str

判断方式:

</>PYTHON
from collections.abc import Iterable

isinstance([1, 2, 3], Iterable)  # True

注意:
可迭代对象 ≠ 迭代器


二、什么是迭代器(Iterator)

1. 迭代器的定义

迭代器是一个对象,它同时满足两个条件:

  1. 实现 __iter__() 方法
  2. 实现 __next__() 方法

判断方式:

</>PYTHON
from collections.abc import Iterator

isinstance(iter([1, 2, 3]), Iterator)  # True

2. iter() 与 next()

</>PYTHON
lst = [1, 2, 3]
it = iter(lst)

print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3
print(next(it))  # StopIteration

核心机制:

  • iter() 创建迭代器
  • next() 获取下一个值
  • 没有元素时抛出 StopIteration

3. 手写一个迭代器

</>PYTHON
class Counter:
    def __init__(self, limit):
        self.limit = limit
        self.current = 0

    def __iter__(self):
        return self

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

使用方式:

</>PYTHON
for i in Counter(3):
    print(i)

输出:

</>CODE
1
2
3

三、什么是生成器(Generator)

生成器是 创建迭代器的更优雅方式

一句话总结:

生成器 = 语法简化的迭代器


1. 生成器函数(yield)

只要函数中出现 yield,它就变成了生成器函数。

</>PYTHON
def count_up(limit):
    current = 0
    while current < limit:
        current += 1
        yield current

使用:

</>PYTHON
for i in count_up(3):
    print(i)

特点:

  • yield 会暂停函数执行
  • 再次调用从暂停位置继续
  • 自动实现迭代器协议

2. 生成器表达式

</>PYTHON
gen = (x * x for x in range(5))

对比列表推导式:

</>PYTHON
lst = [x * x for x in range(5)]  # 立即计算
gen = (x * x for x in range(5)]  # 惰性计算

四、惰性计算(Lazy Evaluation)

生成器的最大优势:按需计算

</>PYTHON
def read_big_file(path):
    with open(path) as f:
        for line in f:
            yield line

优点:

  • 节省内存
  • 支持大文件
  • 支持无限数据流

五、迭代器 vs 生成器

对比项迭代器生成器
写法手动实现yield
可读性一般很好
代码量
本质函数
推荐

结论:

除非必要,不要手写迭代器。


六、常见陷阱

1. 生成器只能遍历一次

</>PYTHON
gen = (i for i in range(3))

list(gen)  # [0, 1, 2]
list(gen)  # []

原因:生成器是消耗型的。


2. 不要依赖生成器中的副作用

</>PYTHON
def gen():
    print("start")
    yield 1
    print("end")

执行顺序由 next() 决定,不直观。


3. 生成器不是列表

</>PYTHON
len(gen)   # 错误
gen[0]     # 错误

七、实战:无限斐波那契数列

</>PYTHON
def fibonacci():
    a, b = 0, 1
    while True:
        yield b
        a, b = b, a + b

使用:

</>PYTHON
fib = fibonacci()
for _ in range(10):
    print(next(fib))

八、总结

  • Iterable:能被 for 遍历
  • Iterator:能被 next 调用
  • Generator:最推荐的迭代方式
  • yield:惰性计算的核心

一句话记忆:

能用生成器,就不要手写迭代器。