首先yield 可以看成是一个return,这是一个最直观的解释,因为yield首先就是个return;
普通的return:就是在程序中返回某个值,返回之后程序就不再运行下去了
看做return之后再把他看成是一个生成器的一部分
print("starting...")
while True:
res = yield 4
print("res:",res)
g = foo()
print(next(g))
print("*"*20)
print(next(g))
返回的是
starting...
4
********************
res: None
4
我直接解释代码运行顺序,相当于代码单步调试
1 程序开始执行的以后,因为foo函数中有yield关键字,所以foo函数并不会真的执行,而是先得到一个生成器g(相当于一个对象)
2 直到调用next方法,foo才开始执行,先执行foo的print方法,再执行while语句。
3 程序遇到yield关键字后,把yield当成一个return后,return一个4之后,程序停止,并没有执行赋值给res的操作
所以现在执行的是第一句的print,和while中返回,并没有执行到最后的print语句
starting...
4
4 执行print(*)好操作
5 又开始执行下边的print(next(g)),这个和上边的意思差不多,不过不同的是,从刚才那个next 停止的地方开始执行
也就是执行res的赋值操作,这个时候要注意,这个时候赋值操作右边是没有值的(因为刚才那个return出去了,并没有赋值操作左边传的参数)
所以这个时候res的赋值是none ,接下来的输出就是none
6 程序会继续在while中执行,并碰到yield后返回4后停止
到这里你可能就明白yield和return的关系和区别了,带yield的函数是一个生成器,而不是一个函数了,这个生成器有一个函数就是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))
print("*"*20)
print(g.send(7))
再看一个这个生成器的send函数的例子,这个例子就把上面那个例子的最后一行换掉了,输出结果:
starting...
4
********************
res: 7
4
先大致说一下send函数的概念:此时你应该注意到上面那个的紫色的字,还有上面那个res的值为什么是None,这个变成了7,到底为什么,这是因为,send是发送一个参数给res的,因为上面讲到,return的时候,并没有把4赋值给res,下次执行的时候只好继续执行赋值操作,只好赋值为None了,而如果用send的话,开始执行的时候,先接着上一次(return 4之后)执行,先把7赋值给了res,然后执行next的作用,遇见下一回的yield,return出结果后结束。
- 程序在执行g.seed(7)的时候,程序会从yield关键字哪一行继续向下运行,send会把7这个值赋给res变量
- 由于seed中包换next方法,所以程序会继续向下执行
- 程序在while中遇到yield后会再次暂停,指导再遇到next或者seed的方法后