在 Python 中,yield
关键字用于定义生成器函数(Generator Function),它的核心作用是实现惰性计算(Lazy Evaluation),允许函数在执行过程中暂停并保存状态,后续可以恢复执行。以下是 yield
的详细作用和典型应用场景:
一、yield
的核心作用
1. 生成器函数
yield
将普通函数转换为生成器函数,调用生成器函数时返回一个生成器对象(Generator Object),而不是直接计算结果。- 生成器对象支持迭代(
for
循环或next()
),每次迭代执行到yield
时返回一个值,并暂停函数状态,下次迭代从暂停处继续执行。
2. 惰性计算(按需生成数据)
- 生成器不会一次性生成所有数据,而是逐次生成,适合处理大数据集或无限序列,避免内存溢出(OOM)。
3. 状态保持
- 生成器函数会记住上次执行的位置和局部变量,每次调用
next()
时恢复执行上下文。
二、yield
与 return
的对比
特性 | yield |
return |
---|---|---|
返回值类型 | 生成器对象(可迭代) | 直接返回结果 |
执行方式 | 多次执行,每次返回一个值 | 执行一次后终止 |
内存占用 | 低(逐个生成数据) | 高(需存储所有结果) |
适用场景 | 大数据、流处理、无限序列 | 小规模、一次性计算结果 |
三、典型使用场景
1. 处理大规模数据
|
|
2. 生成无限序列
|
|
3. 实现协程(Coroutine)
通过 yield
和 send()
实现双向通信:
|
|
四、yield from
简化嵌套生成器
Python 3.3+ 引入 yield from
,用于委托生成器:
|
|
五、注意事项
-
生成器只能遍历一次
生成器对象迭代结束后无法重复使用,需重新创建生成器。
-
生成器与列表的转换
可通过
list(generator)
将生成器结果转为列表(但会丢失惰性计算优势)。 -
性能权衡
生成器适合内存敏感场景,但频繁调用
next()
可能增加 CPU 开销。
六、总结
- 核心价值:
yield
通过惰性计算和状态保持,实现内存高效的数据流处理。 - 适用场景:
- 处理大文件或数据库查询结果(避免内存溢出)。
- 生成无限序列(如斐波那契数列)。
- 实现协程和异步编程模式。
- 替代方案:
- 小数据用
return
+ 列表。 - 高性能场景可结合
itertools
模块优化。
- 小数据用