浅谈 Python 中的 yield——yield的返回值与send()的关系

在 Python 中,yield 通常被认为是"生成多个值"的工具,但其实它的作用远不止如此。尤其当我们配合 .send() 方法使用时,yield 不只是"抛出值",还变成了一个表达式 ------ 能够接收来自外部的输入

这篇文章将深入解释两个关键问题:

  • yield 表达式的值是从哪来的?
  • 使用 send() 和不使用 send() 的区别是什么?

一、基本示例

python 复制代码
def greeter():
    name = yield "你是谁?"
    yield f"你好,{name}"

g = greeter()
print(next(g))         # 输出: 你是谁?
print(g.send("张三"))  # 输出: 你好,张三

重点一:send(x) 会把 x 赋值给上一个 yield 表达式

让我们重点关注这一行代码:

python 复制代码
name = yield "你是谁?"

这是一个"暂停点 + 接收点":

  • yield "你是谁?" 会将 "你是谁?" 发出(返回给调用者),并暂停函数;

  • 当我们调用 g.send("张三") 时,Python 会:

    • 恢复生成器的执行;
    • "张三" 作为 yield 表达式的返回值;
    • 也就是:name = "张三"

✅ 图示等价理解:

python 复制代码
name = yield "你是谁?"
# 调用 g.send("张三") 后,相当于:
name = "张三"

重点二:如果不用 send()yield 表达式的值是 None

来看另一个例子:

python 复制代码
def greeter():
    name = yield "你是谁?"
    print(f"你好,{name}")

g = greeter()
print(next(g))    # 第一次执行,返回 "你是谁?"
print(next(g))    # 第二次执行,没有 send,name 是多少?

✅ 输出:

复制代码
你是谁?
你好,None

因为第二次使用的是 next(g),而不是 send(x),所以:

yield 表达式的返回值默认是 None


二、完整对比总结表

操作方式 功能说明 yield 表达式的值
next(generator) 恢复执行但不提供返回值 None
generator.send(x) 恢复执行并将 x 作为返回值 x(赋值给 yield 表达式)

三、思维模型类比:问答式通信

python 复制代码
question = yield "你是谁?"
  • yield 提出一个问题;
  • 外部使用 send("张三") 作为回答;
  • 于是 question = "张三"

这就像是协程之间的双向通信,是构建调度器、LLM代理、LangGraph等系统的核心通信模式。


四、以三段式协程对话为例

python 复制代码
def dialogue():
    name = yield "你是谁?"
    age = yield f"你好,{name},你几岁?"
    yield f"{name},你今年 {age} 岁了!"

g = dialogue()
print(next(g))           # → "你是谁?"
print(g.send("张三"))    # → "你好,张三,你几岁?"
print(g.send(18))        # → "张三,你今年 18 岁了!"

输出:

复制代码
你是谁?
你好,张三,你几岁?
张三,你今年 18 岁了!

五、总结

  • yield 可以是表达式;
  • send(x)x 作为上一个 yield 表达式的返回值;
  • 如果不用 send() 而用 next(),返回值默认是 None
  • yield + send() 构成了 Python 协程通信的基础机制。

🔚 推荐阅读

相关推荐
A__tao43 分钟前
Elasticsearch Mapping 一键生成 Java 实体类(支持嵌套 + 自动过滤注释)
java·python·elasticsearch
研究点啥好呢1 小时前
Github热门项目推荐 | 创建你的像素风格!
c++·python·node.js·github·开源软件
lly2024061 小时前
C 标准库 - `<stdio.h>`
开发语言
沫璃染墨1 小时前
C++ string 从入门到精通:构造、迭代器、容量接口全解析
c语言·开发语言·c++
jwn9991 小时前
Laravel6.x核心特性全解析
开发语言·php·laravel
迷藏4941 小时前
**发散创新:基于Rust实现的开源合规权限管理框架设计与实践**在现代软件架构中,**权限控制(RBAC)** 已成为保障
java·开发语言·python·rust·开源
功德+n2 小时前
Linux下安装与配置Docker完整详细步骤
linux·运维·服务器·开发语言·docker·centos
明日清晨2 小时前
python扫码登录dy
开发语言·python
我是唐青枫2 小时前
C#.NET gRPC 深入解析:Proto 定义、流式调用与服务间通信取舍
开发语言·c#·.net
JJay.2 小时前
Kotlin 高阶函数学习指南
android·开发语言·kotlin