Python中,yield的关键字以及yield from的概念用法详解
Q1:
在 Python 中,yield 关键字用于定义生成器函数,它是一种特殊的函数,可以在迭代过程中逐一生成值,而不是一次性返回所有结果。
通俗来说,yield 就像一个“暂停按钮”,让函数在返回一个值后暂停执行,等待下一次调用时继续从暂停处运行。
通俗解释
想象你在工厂流水线上生产糖果:
- 普通函数就像一次性把所有糖果生产完,装进一个大盒子返回。
- 使用 yield 的生成器函数则是“边生产边送货”,每次只生产一颗糖果(一个值),送出去后暂停,等你需要下一颗时再继续生产。这样可以节省内存(不用一次存所有糖果),也更灵活(可以随时决定要不要继续生产)。
yield 的核心概念
- 生成器:使用 yield 的函数会返回一个生成器对象,可以用 for 循环或 next() 函数逐一获取值。
- 暂停与恢复:每次调用 yield 时,函数暂停并返回一个值,保存当前状态(包括变量值和执行位置)。下次迭代时从暂停处继续执行。
- 惰性求值:值是按需生成的,只有在请求下一个值时才会计算,适合处理大数据或无限序列。
yield的简单示例
def count_up_to(n): for i in range(n): yield i # 每次返回一个值,暂停函数 # 使用生成器 gen = count_up_to(3) print(next(gen)) # 输出 0 print(next(gen)) # 输出 1 print(next(gen)) # 输出 2 # 或者用 for 循环 for num in count_up_to(3): print(num) # 输出 0, 1, 2
关键点
- 内存效率:生成器不一次性加载所有数据到内存,适合处理大数据或无限序列(如斐波那契数列)。
- 一次迭代:生成器只能迭代一次,耗尽后需重新创建。
- 与 return 的区别:return 终止函数并返回结果,而 yield 暂停函数并返回一个值,保留后续执行能力。
实际应用场景
- 处理大文件:逐行读取文件,而不是一次性加载整个文件。
- 生成无限序列:如无限计数器或随机数生成器。
- 异步编程:在协程中,yield 常用于暂停和恢复执行。
总结:yield 让函数变成“边干边给”的生成器,节省内存、灵活高效,特别适合需要逐个处理数据的场景。
Q2:
yield的概念和用法已经介绍完,那么yield from又该如何理解呢?
直接说yield from 会比较抽象,对待抽象的东西,我们可以先从具像的例子开始理解。
yield from的简单示例:超市分店的库存
假设你是一家连锁超市的总店长,想统计所有分店(包括分店中的分店)的库存。每个分店有自己的库存清单,分店还可能有更小的分店(嵌套结构)。我们用 yield 和 yield from 来实现。
示例代码
def sub_store_inventory(): # 小分店的库存 yield "苹果" yield "香蕉" def main_store_inventory(): # 总店自己的库存 yield "橙子" # 有一个小分店,调用它的库存 yield from sub_store_inventory() # 总店还有其他库存 yield "芒果" # 统计所有库存 inventory = main_store_inventory() for item in inventory: print(item)
输出:
橙子
苹果
香蕉
芒果
解释
- sub_store_inventory 是一个生成器:
- 它用 yield 逐个生成小分店的库存:"苹果" 和 "香蕉"。
- main_store_inventory 是一个生成器:
- 它先 yield 总店自己的库存 "橙子"。
- 然后遇到 yield from sub_store_inventory(),表示“把小分店的库存逐个拿过来”。
- 相当于把 sub_store_inventory 的生成结果("苹果" 和 "香蕉")直接逐个 yield 出来。
- 效果等同于:
for item in sub_store_inventory(): yield item
- 最后 yield 总店的剩余库存 "芒果"。
- 为什么用 yield from?
- 如果不用 yield from,你需要手动写循环来处理 sub_store_inventory() 的结果,代码会更复杂。
- yield from 简化了嵌套生成器的处理,直接“委托”给子生成器,把它的结果逐个 yield 出来。
核心点
- yield from 的作用是把另一个生成器(或可迭代对象)的元素逐个 yield 出来,适合处理嵌套结构。
- 它就像你告诉小分店:“把你的库存直接报上来,我帮你汇总。”

浙公网安备 33010602011771号