python的send方法原理
生成器的 send方法是如何运作的?为什么当生成器被挂起时用它才有意义?
第一个疑问
看一段代码:
>>> def test(val=0):
while True:
y = yield val
print(y)
>>> t = test() # 启用生成器
>>> next(t)
0
>>> next(t)
None
0
这段代码是Next的使用,但唯独有一个疑问:
为什么第二次Next调用后,print(y)输出了None,而不是 0 ?
因为赋值语句从等号右边开始
第一次Next调用后,执行等号右边的表达式 yield val,执行完后函数暂停运行,赋值操作根本没有被执行。
当第二次再运行时才执行赋值(等号左半部分),而生成器恢复运行时,yield初始值为None,所以 y = None
这段代码中Next返回的始终是 0 ,如何在外部与生成器沟通,让她返回不一样的值? 于是用到了send方法
为什么可以不同
再来看send方法:
>>> def test(val=0):
while True:
y = yield val
val = y
>>> t = test()
>>> next(t)
0
>>> t.send('Hello,world')
'Hello,world'
send方法包含与next同样的效果,但还能为生成器传值。
在第一个例子中,第二次运行Next时yield初始值为None,导致将None赋给了y,而不是0。
在本例中使用send恢复生成器,yield初始值不是None,而是send的参数'Hello,world'
所以,send方法与next的不同在于: send首先给生成器传值,再执行和Next相同的操作( 从上次暂停的地方开始,执行到下一个yield ) send(None) 等价于 Next
所以为什么第一次运行生成器send参数只能为None? 因为send首先执行赋值操作,而生成器第一次启动,要赋值给谁?
Because generator-iterators begin execution at the top of the generator's function body, there is no yield expression to receive a value when the generator has just been created. Therefore, calling send() with a non-None argument is prohibited when the generator iterator has just started, and a TypeError is raised if this occurs (presumably due to a logic error of some kind). Thus, before you can communicate with a coroutine you must first call next() or send(None) to advance its execution to the first yield expression.
总结
当有如 y = yield x 这样的句子时,首先执行等号右半部分,再将结果赋给 y,但显然执行完yield就被冻结了,赋值只能在下一次运行生成器时执行,而下一次初始值为None。
send方法可以为生成器传值,send(None) 等价于 Next()
第一次运行生成器时如果用send方法,参数只能为None
————————————————
版权声明:本文为CSDN博主「Sheng_1225」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_28915777/article/details/108186963