news 2026/4/16 9:52:44

Python:yield 表达式详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python:yield 表达式详解

在 Python 中,yield 并不是一种“特殊的返回语句”,也不是为惰性计算或循环结构单独设计的语法技巧。从执行模型的角度看,yield 的核心作用在于:将一次函数执行拆解为一个可暂停、可恢复、可逐步推进的执行过程,并以表达式的形式暴露这一执行边界。

理解 yield,并不是理解“生成器怎么用”,而是理解 Python 如何将执行状态对象化,并使其能够参与函数调用、迭代与控制流程之中。

一、从函数调用语义说起:普通函数是一段一次性执行过程

先从普通函数的执行语义入手:

def f(): a = 1 b = 2 return a + b

当执行:

result = f()

解释器的行为可以概括为:

1、根据 def 语句创建函数对象(该函数对象内部关联了一个代码对象)

2、调用函数时,创建一个新的帧对象,即“执行帧”

3、从函数体起始位置开始顺序执行指令

4、遇到 return 语句:

• 计算返回值

• 销毁执行帧

• 将结果返回给调用方

普通函数的执行帧是一次性的。一旦 return 被执行,该次执行过程即告结束,其执行状态不会被保留,也不可能被恢复。

因此,普通函数在语义上描述的是:从开始到结束的一次完整执行帧生命周期。

二、yield 表达式语法与执行语义定位

1、yield 是表达式,而不是语句

在 Python 3 中,yield 是一种表达式(expression),而不是语句(statement)。

yield 表达式的基本语法结构:

yield <expression>

说明:

(1)<expression> 是一个普通的 Python 表达式;该表达式在执行过程中被求值,其结果作为本次迭代中产出的值交还给调用方。

(2)yield <expression> 的语义作用在于:在执行过程中产出一个值,并暂停当前执行帧。

当 <expression> 被省略时:

yield

其语义等价于:

yield None

即产出值为 None,但暂停执行的语义保持不变。

2、yield 对函数调用语义的根本影响

一旦函数体中出现 yield 表达式,解释器在语法分析阶段就会将该函数判定为生成器函数。这一判定结果会直接影响该函数在调用阶段的语义:

• 调用普通函数 → 立即创建执行帧并执行函数体

• 调用生成器函数 → 返回一个生成器对象,而不立即执行函数体

也就是说,yield 改变的并不是函数体中的某一步行为,而是从定义层面改变了函数调用的执行模型与返回结果类型。

从语言设计角度看,yield 的引入并非为了简化循环或节省内存,而是为了允许:函数的执行过程本身成为一个可被拆解、可被对象化、可被外部逐步驱动的运行期实体。

3、普通函数与生成器函数:定义层与执行层的差异

从定义层面看,Python 中的函数可以分为两类:

• 普通函数:函数体中不包含 yield

• 生成器函数:函数体中至少包含一条 yield 表达式

这一差异在 def 语句执行时即已确定,并体现在函数对象所关联的代码对象上。

两类函数在调用语义上的根本区别在于:

• 调用普通函数时,解释器立即创建执行帧并执行代码

• 调用生成器函数时,解释器返回一个生成器对象,而暂不创建执行帧

生成器对象可以被理解为对生成器函数一次潜在执行过程的封装。

它本身并不等同于执行帧,而是一个运行期控制对象,用于在需要时创建、保存并恢复执行帧。

三、yield 的核心语义:冻结当前执行帧

对于包含 yield 的函数而言,def 语句仅创建函数对象,调用该函数时才返回生成器对象。

执行帧的创建与激活,则发生在生成器对象被首次推进时(如 next() 或 send(None))。

示例:

def g(): x = 1 yield x x += 1 yield x + 1

当执行:

gen = g()next(gen)

解释器的执行过程为:

1、调用 g(),返回生成器对象

2、调用 next(gen):

→ 创建并激活执行帧

→ 从函数体起始位置开始执行

3、执行至 yield x:

→ 对表达式 x 求值

→ 将该值交还给调用方

→ 冻结当前执行帧的状态(包括指令位置、局部变量绑定及相关执行上下文)

这里所谓的“冻结”,指的是执行帧的暂停。即,函数的执行过程尚未完成,其执行状态被完整保留下来,等待后续恢复。

四、恢复执行与执行终止:yield 与 return 的语义分野

当生成器对象被多次推进时,解释器不会重新调用生成器函数,也不会重新创建执行帧。

gen = g()print(next(gen)) # 1print(next(gen)) # 3print(next(gen)) # StopIteration

执行过程是:

1、第一次 next(gen):

→ 创建并激活执行帧

→ 执行至第一个 yield,返回 yield 表达式的值

→ 然后冻结执行帧

2、第二次 next(gen):

→ 恢复此前冻结的执行帧,从上一次 yield 之后继续执行

→ 执行至第二个 yield,返回此 yield 表达式的值

3、第三次 next(gen):

→ 恢复冻结的执行帧,从第二次 yield 之后继续执行

→ 已到生成器函数底部,无法继续推进,抛出 StopIteration,销毁执行帧

整个过程中,推进的始终是同一个执行帧。

由此可以清晰地区分 yield 与 return 的本质差异:

(1)yield 表示执行过程的暂停点

• 执行帧被保留

• 执行状态可恢复

(2)return 表示执行过程的终止点

• 执行帧被销毁

• 执行过程不可恢复

当生成器函数运行至末尾,或在生成器函数内显式执行 return 时:

• 解释器向调用方抛出 StopIteration

• 执行帧被销毁

• 生成器对象进入终止态

因此,两者的区别并不在于是否“返回值”,而在于是否保留并允许继续推进当前执行帧。

五、yield 作为表达式:值的双向流动与 send 机制

绝大多数 Python 表达式的值,均在其执行当下立即确定。但 yield 是一个例外。

yield 表达式的产出值在执行当下确定,而该表达式的求值结果则延迟到下一次恢复执行时,由外部注入。

示例:

def gen(): x = yield 1 yield x

当执行:

g = gen()next(g) # 产出 1g.send("hello") # 将 "hello" 注入

g.send("hello") 并不是向生成器“整体”发送一个值,而是将 "hello" 作为上一次暂停点处的 yield 1 这个表达式的求值结果,然后将该值绑定给变量 x。

可以这样说,第一次 next(g) 大致等价于:

g.send(None)

也就是说,首次可使用 send() 向生成器对象发送 None 值来创建并激活执行帧。

不过,要注意的是,在生成器尚未启动之前,不能直接使用 send() 向生成器发送非 None 值,解释器将抛出 TypeError。原因是:

• 尚未创建执行帧

• 尚不存在暂停点

因而不存在可接收值的 yield 表达式。

六、yield from 的基本语义概览

yield from 是一种用于委托执行控制权的表达式。它在一段时间内暂停当前生成器的执行,并将执行推进、值注入、异常处理与终止请求统一转交给被委托对象;在被委托对象完成后,再恢复自身执行并接收其完成态返回值。

请参阅:

《Python:yield from 表达式详解》

📘 小结

yield 是一种用于冻结执行帧的表达式。它并不返回生成器对象,而是在生成器执行过程中产出值并暂停当前执行帧,从而将一次函数执行拆解为多个可恢复的执行阶段。作为表达式,yield 还支持在恢复执行时接收外部注入的值。

理解 yield 的语义,有助于从执行模型层面把握生成器、send 与 yield from 等机制的统一设计思想。

“点赞有美意,赞赏是鼓励”

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/12 8:11:54

Qwen-Image-Edit-F2P在嵌入式Linux系统上的优化部署

Qwen-Image-Edit-F2P在嵌入式Linux系统上的优化部署 想象一下&#xff0c;你有一台小巧的智能相机或者一个便携式的创作设备&#xff0c;它不仅能拍照&#xff0c;还能根据你上传的人脸照片&#xff0c;瞬间生成一张风格各异、质感精美的全身艺术照。这听起来像是需要一台高性…

作者头像 李华
网站建设 2026/4/15 15:55:38

RMBG-2.0在MySQL数据库中的图像处理应用

RMBG-2.0在MySQL数据库中的图像处理应用 电商平台、内容社区或者企业内部系统里&#xff0c;经常有成千上万的商品图片、用户头像、内容配图存在数据库里。这些图片往往背景杂乱&#xff0c;直接展示效果不佳&#xff0c;需要统一处理成透明背景或者换上干净的场景。一张张手动…

作者头像 李华
网站建设 2026/4/15 14:46:38

快速上手:美胸-年美-造相Z-Turbo镜像的完整操作流程

快速上手&#xff1a;美胸-年美-造相Z-Turbo镜像的完整操作流程 1. 环境准备与快速部署 美胸-年美-造相Z-Turbo镜像是一个基于Xinference部署的文生图模型服务&#xff0c;使用Gradio提供友好的Web界面。这个镜像特别适合想要快速体验AI图像生成的用户&#xff0c;无需复杂的…

作者头像 李华
网站建设 2026/4/15 2:33:11

3大场景解锁悬浮浏览器效率革命:Windows透明浏览新体验

3大场景解锁悬浮浏览器效率革命&#xff1a;Windows透明浏览新体验 【免费下载链接】glass-browser A floating, always-on-top, transparent browser for Windows. 项目地址: https://gitcode.com/gh_mirrors/gl/glass-browser 在多任务处理成为常态的今天&#xff0c;…

作者头像 李华
网站建设 2026/4/15 21:44:55

.accelerate框架优化BEYOND REALITY Z-Image推理速度

.accelerate框架优化BEYOND REALITY Z-Image推理速度 1. 为什么Z-Image需要加速&#xff1a;从胶片美学追求到工程落地的现实挑战 BEYOND REALITY Z-Image系列模型在人像生成领域确实让人眼前一亮。它把胶片摄影那种温润的光影、细腻的皮肤纹理和富有层次的环境细节&#xff…

作者头像 李华