1. 视角一:作为“产出器”(对外返回值)
yield 会把后面的值返回给外部调用者(比如 next() 或 for 循环),然后暂停函数执行。yield 后面的表达式结果。next() 时。2. 视角二:作为“接收器”(对内接收值)
yield 处时,外部可以通过 gen.send(value) 恢复它。此时,外部传入的这个 value,就会成为这个 yield 表达式本身的返回值!核心口诀:next()相当于send(None)。外部传什么值,yield
def my_generator(): print("生成器启动") # 这里的 yield 既向外返回 1,又准备接收外部传来的值赋给 res res = yield 1 print(f"我收到了外部传来的值: {res}") yield 2 # 创建生成器对象 gen = my_generator() # 第一步:启动生成器,遇到 yield 1 暂停 # 此时向外返回 1,但 res 还没被赋值(因为还没恢复) print(next(gen)) # 输出: # 生成器启动 # 1 # 第二步:使用 send() 恢复,传入 "Hello" # 这个 "Hello" 会作为上一个 yield 表达式的返回值,赋给 res print(gen.send("Hello")) # 输出: # 我收到了外部传来的值: Hello # 2 # 第三步:如果用 next() 恢复,相当于 send(None) # print(next(gen)) # 输出: 我收到了外部传来的值: None
yield 有一个极其反直觉的特性:赋值是延迟发生的。res = yield 1 这行代码中:1 抛给外部,然后挂起(暂停)。res = ... 这个赋值动作根本没有执行,它被冻结了。next() 或 send() 唤醒它时,Python 才会把外部传来的值赋给 res,然后继续往下执行。
def my_generator(): print("生成器启动") # 这里的 yield 既向外返回 1,又准备接收外部传来的值赋给 res res = yield 1 print(f"我收到了外部传来的值: {res}") yield 2 # 创建生成器对象 gen = my_generator() # 第一步:启动生成器,遇到 yield 1 暂停 # 此时向外返回 1,但 res 还没被赋值(因为还没恢复) print(next(gen)) # 输出: # 生成器启动 # 1 # 第二步:使用 send() 恢复,传入 "Hello" # 这个 "Hello" 会作为上一个 yield 表达式的返回值,赋给 res print(gen.send("Hello")) # 输出: # 我收到了外部传来的值: Hello # 2 # 第三步:如果用 next() 恢复,相当于 send(None) # print(next(gen)) # 输出: 我收到了外部传来的值: None
yield 后面的表达式结果。next() 时。
1 抛给外部,然后挂起(暂停)。res = ... 这个赋值动作根本没有执行,它被冻结了。next() 或 send() 唤醒它时,Python 才会把外部传来的值赋给 res,然后继续往下执行。
yield 有返回值:对外返回 yield 后的值,对内接收 send() 传入的值。next() 传入 None,send("abc") 传入 "abc"。