send()是生成器的一个特殊方法,它不仅能恢复生成器的执行,还能向生成器发送一个值,这个值会成为当前yield表达式的返回值。
一、send()的核心作用
| 方法 | 作用 | 能否传值 |
|---|---|---|
next(g) | 恢复执行到下一个yield | 不能 |
g.send(value) | 恢复执行,并传入一个值 | 能 |
说明:send(value)传入的值会赋值给当前yield表达式。
def demo(): x = yield 1 # yield 1 返回给外部,同时接收外部 send 的值 print(f"收到: {x}") y = yield 2 print(f"收到: {y}") yield 3 g = demo() print(next(g)) # 1(执行到第一个 yield,暂停) print(g.send(100)) # 100 赋给 x → 打印"收到: 100" → 执行到 yield 2 → 返回 2 print(g.send(200)) # 200 赋给 y → 打印"收到: 200" → 执行到 yield 3 → 返回 3二、执行过程
代码示例
def accumulator(): total = 0 while True: value = yield total # ① 返回当前 total,等待接收值 if value is None: break total += value gen = accumulator()逐步执行
| 步骤 | 代码 | 执行过程 | 返回值 |
|---|---|---|---|
| 1 | next(gen) | 执行到yield total,total=0,暂停 | 0 |
| 2 | gen.send(10) | ①10赋给value② total += 10→total=10③ 回到循环,执行到 yield total,暂停 | 10 |
| 3 | gen.send(20) | ①20赋给value② total += 20→total=30③ 回到循环,执行到 yield total,暂停 | 30 |
| 4 | gen.send(None) | value=None→break→ 生成器结束 | StopIteration |
三、send()和next()的等价关系
next(g) # 等价于 g.send(None)实际上,next(g)内部调用的就是g.send(None)。
def gen(): yield 1 yield 2 g = gen() print(next(g)) # 1 print(g.send(None)) # 2(等价于 next(g))四、第一次调用不能用send()
规则:生成器第一次恢复执行时,必须用next(g)或g.send(None),不能send非None的值。
def gen(): x = yield 1 print(x) g = gen() # g.send(100) # TypeError: can't send non-None value to a just-started generator next(g) # 必须先启动 g.send(100) # 之后可以 send原因:生成器在第一次执行前没有yield表达式来接收值。
五、send()的执行流程图
send(value)把value传给当前暂停的yield表达式,yield表达式的返回值就是send传入的值。第一次调用必须用next(g)或send(None)来启动生成器。