浅谈 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 协程通信的基础机制。

🔚 推荐阅读

相关推荐
AI人工智能+电脑小能手3 分钟前
【大白话说Java面试题 第112题】【并发篇】第12题:AQS 中节点的入队时机有哪些?
java·开发语言·面试
SilentSamsara4 分钟前
RAG 系统入门:LangChain/LlamaIndex + Chroma 向量数据库的检索增强实战
数据库·人工智能·python·青少年编程·langchain
IT WorryFree5 分钟前
Zabbix 7.4 API 可同步全量参数清单(同步第三方系统专用)
java·开发语言·zabbix
码云骑士16 分钟前
06-Python装饰器从入门到源码(上)-闭包与自由变量
开发语言·python
码云骑士25 分钟前
10-Python运行时内存模型-栈帧-堆-引用计数-GC分代回收的全景图
开发语言·python
智码看视界32 分钟前
老梁聊全栈系列 JavaScript语言本质:从原型链到异步编程的深度解析
开发语言·javascript·全栈·javascript核心
AI科技星35 分钟前
数术工坊・八卷全书【本源创世终极版・万世定稿】
开发语言·网络·量子计算·拓扑学
雾沉川37 分钟前
Visual C++ 运行库合集 v105.0 部署与故障排查技术指南
开发语言·c++·dll
码云骑士38 分钟前
02-Python可变对象与不可变对象(上)-赋值陷阱与函数传参的暗坑
开发语言·python