Skip to content

Python 迭代器和生成器

迭代器和生成器是 Python 中用于处理数据序列的强大且高效的工具。它们允许你按需处理数据,而不是一次性将所有数据加载到内存中,这在处理大数据集时尤其有用。

迭代器 (Iterators)

迭代器是一个表示数据流的对象。它实现了迭代器协议,该协议包含两个方法:__iter__()__next__()

  • 可迭代对象 (Iterable): 任何可以被 for 循环遍历的对象都是可迭代对象,例如列表、元组、字符串。当你对一个可迭代对象使用 iter() 函数时,你会得到一个迭代器。
  • 迭代器 (Iterator): 迭代器对象负责在循环中一次返回一个元素。它使用 next() 函数来获取下一个值。当没有更多数据时,next() 会引发 StopIteration 异常,for 循环会自动捕获这个异常并结束循环。

for 循环的内部工作原理:

python
my_list = [1, 2, 3]

# 1. for 循环首先调用 iter() 获取迭代器
my_iterator = iter(my_list)

# 2. 然后循环调用 next() 获取每个元素
print(next(my_iterator)) # 输出: 1
print(next(my_iterator)) # 输出: 2
print(next(my_iterator)) # 输出: 3

# 3. 当元素耗尽时,引发 StopIteration
# print(next(my_iterator)) # StopIteration

迭代器是“一次性”的。一旦你遍历完一个迭代器,它就耗尽了,不能再次使用。

生成器 (Generators)

生成器是一种特殊类型的迭代器,但你不需要手动创建类来实现 __iter__()__next__() 方法。创建生成器有两种主要方式:

1. 生成器函数

生成器函数是一个使用 yield 关键字的函数。当你调用一个生成器函数时,它不会立即执行,而是返回一个生成器对象(它也是一个迭代器)。

每次在生成器上调用 next() 时,函数会执行到 yield 语句处,yield 会“产出”一个值,然后函数会暂停执行,并保存其当前状态(包括局部变量和指令指针)。下次再调用 next() 时,函数会从上次暂停的地方继续执行。

示例:

python
def simple_generator():
    print("Generator started")
    yield 1
    print("Generator resumed")
    yield 2
    print("Generator resumed again")
    yield 3
    print("Generator finished")

# 创建生成器对象
gen = simple_generator()

# 逐个获取值
print(next(gen))
# 输出:
# Generator started
# 1

print(next(gen))
# 输出:
# Generator resumed
# 2

# 也可以用 for 循环遍历
for value in simple_generator():
    print(f"For loop got: {value}")

2. 生成器表达式

生成器表达式提供了一种更简洁的方式来创建生成器,其语法类似于列表推导式,但使用圆括号 () 而不是方括号 []

python
# 列表推导式:立即创建完整列表,占用内存
my_list = [x*x for x in range(5)]
print(my_list) # 输出: [0, 1, 4, 9, 16]

# 生成器表达式:创建一个生成器对象,按需生成值,节省内存
my_generator = (x*x for x in range(5))
print(my_generator) # 输出: <generator object <genexpr> at ...>

# 遍历生成器来获取值
for value in my_generator:
    print(value)
# 输出: 0, 1, 4, 9, 16

为什么使用生成器?

  1. 内存效率: 生成器按需生成值,不会一次性在内存中存储整个序列。这使得处理非常大(甚至是无限)的数据流成为可能。
  2. 代码简洁: 生成器函数和表达式比手动创建迭代器类要简单得多。
  3. 可读性强: 它们清晰地表达了数据是如何按序列生成的逻辑。

本站内容仅供学习和研究使用。