网易首页 > 网易号 > 正文 申请入驻

Python:yield 表达式详解

0
分享至

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

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

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

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

    return a + b

当执行:

result = f()

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

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

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

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

4、遇到 return 语句:

• 计算返回值

• 销毁执行帧

• 将结果返回给调用方

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

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

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

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

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

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

yield 

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

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

当 被省略时:

yield

其语义等价于:

yield None

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

示例:

    yield x + 1

当执行:

next(gen)

解释器的执行过程为:

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

2、调用 next(gen):

→ 创建并激活执行帧

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

3、执行至 yield x:

→ 对表达式 x 求值

→ 将该值交还给调用方

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

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

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

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

print(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 表达式的产出值在执行当下确定,而该表达式的求值结果则延迟到下一次恢复执行时,由外部注入。

示例:

    yield x

当执行:

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

请参阅:

小结

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

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


点赞有美意,赞赏是鼓励

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
最孤独婚车后续:新郎新娘颜值高,别克正式回应大格局送上祝福

最孤独婚车后续:新郎新娘颜值高,别克正式回应大格局送上祝福

林轻吟
2026-02-12 22:13:12
摊牌了,孙颖莎王楚钦迎喜讯,国乒公布,大头愿望达成,父母开心

摊牌了,孙颖莎王楚钦迎喜讯,国乒公布,大头愿望达成,父母开心

卿子书
2026-02-14 21:19:59
“炒饭综合征”,致男子多脏器衰竭

“炒饭综合征”,致男子多脏器衰竭

中国日报
2026-02-02 18:16:23
要开始了!伊朗,在劫难逃了!

要开始了!伊朗,在劫难逃了!

大嘴说天下
2026-01-25 19:59:24
向太向华强郭碧婷在新加坡被偶遇,向太不像阔太,郭碧婷成黄脸婆

向太向华强郭碧婷在新加坡被偶遇,向太不像阔太,郭碧婷成黄脸婆

科学发掘
2026-02-14 07:52:27
潮汕婚礼丈母娘火了,打扮娇艳比新娘还抢镜,网友:感觉有点不对

潮汕婚礼丈母娘火了,打扮娇艳比新娘还抢镜,网友:感觉有点不对

梅子的小情绪
2026-02-08 19:59:04
正面回怼奇葩亲戚是啥体验?网友:我家里人也说我说话太厉害了

正面回怼奇葩亲戚是啥体验?网友:我家里人也说我说话太厉害了

解读热点事件
2026-02-06 00:51:21
16GB+1TB!新机官宣:2月26日,正式全球首发!

16GB+1TB!新机官宣:2月26日,正式全球首发!

科技堡垒
2026-02-12 12:24:27
海南“封关”,美国和新加坡竟然没有发声?

海南“封关”,美国和新加坡竟然没有发声?

流苏晚晴
2025-12-24 18:12:19
内蒙古一200斤男子欠5000万不还,被债主装进铁笼沉入80米水库,谁料,2年后才被捞出...

内蒙古一200斤男子欠5000万不还,被债主装进铁笼沉入80米水库,谁料,2年后才被捞出...

品读时刻
2026-02-11 17:18:30
杨瀚森还在长高?新秀赛玩嗨调侃想亲约基奇 拓媒赞必能突破瓶颈

杨瀚森还在长高?新秀赛玩嗨调侃想亲约基奇 拓媒赞必能突破瓶颈

颜小白的篮球梦
2026-02-14 20:47:11
建国后的陈昌浩:只当副局长,多次向老部下道歉,感激毛主席宽恕

建国后的陈昌浩:只当副局长,多次向老部下道歉,感激毛主席宽恕

搜史君
2026-02-14 07:00:09
你是如何意外发现自己生病的?网友:头疼十几年发现是心脏有问题

你是如何意外发现自己生病的?网友:头疼十几年发现是心脏有问题

带你感受人间冷暖
2026-02-11 15:53:14
1979年,党中央抓捕了许世友儿子,许世友得知后表示:直接枪毙!

1979年,党中央抓捕了许世友儿子,许世友得知后表示:直接枪毙!

兴趣知识
2025-11-25 00:53:07
很多人以为殉葬就是把活人关进地宫,门一关,他们只能哭喊着等死

很多人以为殉葬就是把活人关进地宫,门一关,他们只能哭喊着等死

忠于法纪
2026-01-18 17:42:24
美国历史上第一位二百五总统即将诞生,就是当今美国总统特朗普…

美国历史上第一位二百五总统即将诞生,就是当今美国总统特朗普…

福建平子
2026-02-08 13:17:52
09年凯丰儿子参观南方局旧址,当众质问馆长:怎么没有我父亲的像

09年凯丰儿子参观南方局旧址,当众质问馆长:怎么没有我父亲的像

鹤羽说个事
2026-01-17 16:40:11
现在国内买丰田赛那全世界最便宜,得感谢长城魏建军

现在国内买丰田赛那全世界最便宜,得感谢长城魏建军

源Auto
2026-02-14 18:50:08
NBA夺冠概率出炉!火箭湖人均为4%骑士7%屈居第4 第一39%断档领跑

NBA夺冠概率出炉!火箭湖人均为4%骑士7%屈居第4 第一39%断档领跑

锅子篮球
2026-02-14 20:19:26
26岁全身溃烂不治而亡,被全家8口吸血多年

26岁全身溃烂不治而亡,被全家8口吸血多年

仙味少女心
2026-01-31 23:14:30
2026-02-14 23:56:49
MediaTea
MediaTea
专业的数字媒体、新媒体技术
1754文章数 74关注度
往期回顾 全部

科技要闻

字节跳动官宣豆包大模型今日进入2.0阶段

头条要闻

福州街头发现一流浪老人身份成谜 程序员精准破解方言

头条要闻

福州街头发现一流浪老人身份成谜 程序员精准破解方言

体育要闻

最戏剧性的花滑男单,冠军为什么是他?

娱乐要闻

春晚第五次联排路透 明星积极饭撒互动

财经要闻

谁在掌控你的胃?起底百亿"飘香剂"江湖

汽车要闻

星光730新春促销开启 80天销量破2.6万台

态度原创

家居
旅游
艺术
游戏
数码

家居要闻

中古雅韵 乐韵伴日常

旅游要闻

这个春节不必远走,来芦芽山感受不一样的年味!

艺术要闻

418米!浙江最高楼,即将“破土而出”

《零 ~红蝶~ REMAKE》试玩报告:和无名野鬼大战二十回合"/> 主站 商城 论坛 自运营 登录 注册 《零 ~红蝶~ REMAKE》试玩报告:和无...

数码要闻

LG新推耳机,Lite和Plus功能差异竟这么大!

无障碍浏览 进入关怀版