引言
yield是一个表达式(Expression)
比如:m = yield 5
表达式(yield 5)的返回值将赋值给m,所以,认为 m = 5 是错误的。
表达式(yield 5)的返回值来自send(msg)方法,即m=msg
理解关键点:
①调用next()或send()函数返回的是下一个yield表达式的参数(yield后面的值),
②yield表达式的(返回)值不是yield后面的参数,而是通过send()函数传入的值,
next() 和 x.send()
next(x) 和 x.send(None) 作用是一样的,无论是send还是next,都会从上次执行的yield那一行开始执行,并且执行到下一个yield,这个yield表达式是要执行的(将yield后的参数返回给调用这次执行的next或send()),但是这一行(将yield表达式赋给左值,例如a = (yield 1))暂不执行。下一次调用send(msg)时,从这一行开始执行(将msg作为(yield 1)的返回值赋给a)。
以上有点绕。。详见代码:
>>> def f():
print('first')
a = yield 1 #函数包含了yield,这意味着这个函数是一个Generator,参数1作为next()的返回值①②
print(a)
print('second')
b = yield 2 #参数2作为调用next或send时的返回值。
print(b)
print('third')
c = yield 3
print(c)
print('fourth')
d = yield 4
print(d)
>>> x=f()#f()中有yield表达式,被调用后没有立即执行
>>> aa=next(x)#①next()语句将恢复Generator执行,直到第一个yield表达式处,即执行停止在a = yield 1
first
>>> print(aa)
1 #①已经将yield 1的参数作为表达式的返回值,传给了aa
>>> bb=x.send('msg1')#②从'a = yield 1'开始执行,将send()的参数msg1传给b。执行停止在b = yield 2,并将yield 2的参数2传出来给bb
msg1
second
>>> print(bb)
2
>>> cc=next(x)#②从'b = yield 2'开始执行,next(x)相当于x.send(None),None传给b。执行停止在c = yield 3,并将yield 3的参数3传给cc
None
third
>>> print(cc)
3
>>> dd=x.send('msg3')
msg3
fourth
>>> print(dd)
4
>>> ee=x.send('msg4')#再次调用x.send()时,从'd = yield 4'开始执行,(将msg4传给d)直到找到下一个yield表达式。由于后面没有yield了,因此会拋出异常
msg4
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
ee=x.send('msg4')
StopIteration
>>> print(ee)#由于后面没有yield了,也没有参数回传给ee
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
print(ee)
NameError: name 'ee' is not defined
>>>
ps.第一次调用时,请使用next(x)或是x.send(None),不能使用send发送一个非None的值,否则会出错,因为没有yield语句来接收这个值。
以上为我对yield的理解,有不对的地方欢迎指出,谢谢!