首先,如果你还没有对yield有个初步分认识,那么你先把yield看做“return”,这个是直观的,它首先是个return,普通的return是什么意思,就是在程序中返回某个值,返回之后程序就不再往下运行了。而yield 与return有些区别,那先看下面的程序,先初步yield的使用:
def foo(): print("starting...") while True: res = yield 4 print("res:",res) g = foo() print(next(g)) >>>4 print("*"*20) print(next(g)) >>>res: None >>>4
到这里你可能就明白yield和return的关系和区别了,带yield的函数是一个生成器(generator保存的是算法),而不是一个函数了,这个生成器有一个函数就是next函数,next就相当于“下一步”生成哪个数,第二次的next开始的地方是接着上一次的next停止的地方执行的,所以调用next的时候,生成器并不会从foo函数的开始执行,只是接着上一步停止的地方开始,然后遇到yield后,return出要生成的数,此步就结束。
def foo(): print("starting...") while True: res = yield 4 print("res:",res) g = foo() print(next(g)) #>>>4 print("*"*20) print(next(g)) #>>>res: None #>>>4
程序分析:
如何才能实现给res赋值呢,再看一个这个生成器的send函数的例子:
def foo(): print("starting...") while True: res = yield 4 print("res:",res) g = foo() print(next(g)) #>>>4 print("*"*20) print(g.send(7)) #>>>res: 7 #>>>4
send函数的概念:此时你应该注意到上面那个res的值为什么是None,这个变成了7,到底为什么?这是因为,send是发送一个参数给res的,因为上面讲到,return的时候,并没有把4赋值给res,下次执行的时候只好继续执行赋值操作,只好赋值为None了,而如果用send的话,开始执行的时候,先接着上一次(return 4之后)执行,先把7赋值给了res,然后执行next的作用,遇见下一回的yield,return出结果后结束。
发现, send()和next()都可以让生成器向下执行, 不同的是, send(arg)通过一个参数, 给yield res整体赋值.
需要注意的是, 在生成器的第一次使用时, 由于程序并未执行到yield, 所以此时通过send()函数传参调用生成器会报错TypeError: can‘t send non-None value to a just-started generator, 但是可以传入参数None 来使生成器走到yield处
原文:https://www.cnblogs.com/paulwinflo/p/12260199.html