如何在 Python 中使用生成器(yield 语句)
了解如何用 Python 编写生成器。了解yield关键字、惰性求值、内存优化,并将生成器与列表结构进行比较。
概述
当处理大量数据集、日志文件或无限数据流时,同时将所有元素加载到内存中(例如返回一个大列表)很容易耗尽系统 RAM 并使应用程序崩溃。 Python 提供了一个出色的、节省内存的解决方案:生成器。
生成器是一种特殊类型的函数,它返回惰性迭代器。生成器不是一次计算所有值并返回它们,而是根据请求逐一生成值。主要区别在于“yield”声明。当生成器函数调用“yield”时,它会暂停其执行状态(变量、指令指针)并返回生成的值。当请求下一个值时,该函数将从暂停处准确恢复。
由于生成器计算是延迟执行的,因此无论数据集大小如何,它们都使用几乎为零的内存。 Python 还支持生成器表达式,它使用括号语法“(x for x in data)”来创建轻量级内联生成器,而无需声明完整函数。
代码和执行输出
该脚本演示了使用生成器函数以及yield 语句和生成器表达式来生成序列。
generators_demo.py
在编辑器中尝试# 1. Generator function using yield
def count_up_to(limit):
count = 1
while count <= limit:
yield count
count += 1
# Instantiating the generator
counter = count_up_to(3)
print("Memory safe generator instantiated.")
# Fetching values manually
print("Next 1:", next(counter))
print("Next 2:", next(counter))
print("Next 3:", next(counter))
# 2. Iterating with a for loop (automatically handles StopIteration)
print("\n--- Looping over generator ---")
for num in count_up_to(4):
print("Num:", num)
# 3. Generator expression (Shorthand syntax)
squares_gen = (x**2 for x in range(1, 4))
print("\nGenerator expression elements:")
print(list(squares_gen)) # Cast to list to print all elements端子输出
Memory safe generator instantiated.
Next 1: 1
Next 2: 2
Next 3: 3
--- Looping over generator ---
Num: 1
Num: 2
Num: 3
Num: 4
Generator expression elements:
[1, 4, 9]逐步实施
- 使用标准 def 关键字定义函数。
- 使用yield 关键字而不是return 将yield 值返回到迭代器流。
- 使用 for 循环迭代生成器或调用内置的 next(gen) 函数来提取值。
- 使用生成器表达式(使用括号)进行简单的内联惰性转换。
常见问题解答
与列表相比,生成器的主要优点是什么?
内存效率。列表同时将所有元素存储在 RAM 中,而生成器则根据需要逐一生成项目,从而允许您处理大于系统总内存的数据集。
当生成器用完物品时会发生什么?
Python 引发 StopIteration 异常。 for 循环会自动捕获此异常以正常退出循环,但在耗尽的生成器上手动调用 next() 将引发异常。
相关主题
推荐的 Python 资源
通过相关的交互式教程、备忘单和代码比较来扩展您的知识。