yield

ZaynPei Lv6

yield 是 Python 中一个功能强大的关键字,它主要用于创建生成器 (Generator)。理解 yield 的关键在于理解生成器是如何工作的。简而言之,当一个函数包含 yield 关键字时,它就不再是一个普通的函数,而是一个生成器函数。

生成器是一种特殊的迭代器

与一次性计算并返回所有结果的普通函数不同,生成器函数会返回一个生成器对象。这个对象可以按需、逐个地“生成”结果,而不是一次性将所有结果都存储在内存中, 它是一种惰性求值的迭代器。

  • 普通函数 (return): 执行 -> 计算所有结果 -> 返回结果 -> 结束。

  • 生成器函数 (yield): 调用 -> 返回一个生成器对象 (不执行代码) -> 迭代时, 当执行到 yield才“产出”一个值并暂停 -> 等待下一次迭代 -> 从暂停处继续执行。

yield示例

下面的simple_generator函数内部包含了 yield,所以它现在是一个生成器函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def simple_generator():
print("生成器开始执行...")
yield 1

print("生成器继续执行...")
yield 2

print("生成器最后一次执行...")
yield 3

print("生成器执行结束。")

# 调用生成器函数,返回一个生成器对象
my_gen = simple_generator()

print(type(my_gen))
print(my_gen)

当执行上述代码时, 输出并不会包含"生成器开始执行..."等内部代码. 因为yield的存在, 它只是创建并返回了一个生成器对象,这个对象处于“待命”状态。

1
2
<class 'generator'>
<generator object simple_generator at 0x...>
而当采用next()函数或者for循环时, 才能来驱动生成器执行并获取其产出的值。
1
2
3
# 重新创建一个生成器对象
for value in simple_generator():
print(f"For 循环获取到的值: {value}")
输出结果如下:
1
2
3
4
5
6
7
生成器开始执行...
For 循环获取到的值: 1
生成器继续执行...
For 循环获取到的值: 2
生成器最后一次执行...
For 循环获取到的值: 3
生成器执行结束。

yield优势

  • 极高的内存效率: 这是 yield 最突出的优点。生成器按需生成值,在任何时刻只有一个值存在于内存中。对于处理大规模数据集、文件流或无穷序列,这是至关重要的。
  • 能够处理无限序列 由于其“懒加载”的特性,你可以轻松定义一个无限序列的生成器,这是列表或元组无法做到的。
  • 代码逻辑更清晰、简洁 对于需要维护内部状态的复杂迭代逻辑(例如,遍历一个树状结构),使用生成器函数通常比自己实现一个迭代器类(包含 __iter____next__ 方法)要简单得多,代码也更具可读性。
On this page
yield