总结:可以把send()看成是next()的升级版。send()不仅能像next()一样触发生成器的一个迭代,还能传入一个值给 yield语句。 看下面一个列子:
def func(): y = 1 while True: x = yield y y += 1 print('接收了x = {}'.format(x)) f = func() # f是一个初始化好的生成器 # print('传入send(100):', f.send(100)) # 在生成器刚初始化时,不能用send()传入数据,否则会报错。 可以用send(None)。 print('第一次 next():', next(f)) # 生成器启动(激活生成器),代码停在‘x = yield y’这里, # 传入的值为None, next()相当于send(None),产生第一个yield值1。 print('第二次 next():', next(f)) # next()函数触发生成器,从‘y+=1’开始运行,y变成了2, # 最后再次停在‘x=yield y’处,产生一个yield值2,因为没有接收到send值,所以x=None。 print('传入send(10):', f.send(10)) # 此时收到send(10), yield语句被赋值为10,即‘x=yield y =10’,⇨ ‘x=10’。 # 但不影响yield自身产生的值,会接着运行‘y+=1‘,y变成3, # 所以仍会有一个‘next()’产生一个yield值3,再次停在‘x=yield y’处。 # 此处敲黑板:send()带有next()功能。 print('第三次 next():', next(f)) # next()函数触发生成器,从’y+=1‘开始运行,y变成了4, # 然后再次停在’x=yield y‘,产生一个yield值4,没有接收到send值,所以x=None。 f.close() # close()关闭生成器. #print('第四次 next():', next(f)) # 因为 close()关闭生成器,所以会产生StopIteration错误。运行后的结果为:
第一次 next(): 1 接收了x = None 第二次 next(): 2 接收了x = 10 传入send(10): 3 接收了x = None 第三次 next(): 4send() 有两个功能: 1、向当前迭代的“位置"发送值。 2、抛出下一个值。 例子如下:
def fun_yield(): yield 1 a = yield 2 print(a) yield 3 return 4 f = fun_yield() print(next(f)) # 启动生成器,第一次迭代出 1, 代码停在此处。 print(f.send('这是在第二次迭代中传递的值')) # 这时send传进去的值是赋给代码所停的yield位置处,即上面 1 的地方。 # 再实现”next()“功能,迭代出 第二个值 2,然后代码停在 yield 2 的地方 。 print(f.send('这是在第三次迭代中传递的值')) # 因为此时代码停在 yield 2 的地方,所以这时 send()进去的值 赋给了 a,相当于给a重新赋值了。 # 再实现 next() 功能,代码运行到下个 yield 处,所以会 print(a),再迭代出 3。得到的结果为:
1 2 这是在第三次迭代中传递的值 3这说明,虽然 a = yield 2 是在第二个迭代中的,但实际上 a 的值是第三次迭代时传进去的。 具体理解,可以看上面代码的注释。