这篇博文讲的挺好的,但在读完后,自己仍然对yield、send、yield返回值等概念不清楚,于是,做了两个小试验。
试验一:yield语句的返回值
1 def xyz():
2 print('xyz 0')
3 while True:
4 print('xyz 1')
5 data = yield 2
6 print('xyz 2, data = ', data)
7
8 if __name__ == '__main__':
9 mg = xyz()
10 for _ in range(3):
11 print('\nmain: _ = ', _)
12 print('main:', next(mg))
结果:
main: _ = 0
xyz 0
xyz 1
main: 2
main: _ = 1
xyz 2, data = None
xyz 1
main: 2
main: _ = 2
xyz 2, data = None
xyz 1
main: 2
介绍:
定义了生成器函数xyz(),使用语句data = yield 2;
旧的想法:data会等于2;
测试结果:data等于None;
执行next(mg)函数时,控制权交给了xyz()函数——第一次执行xyz()函数,输出了xyz 0,再进入循环,执行yield语句;
yield生成了2,控制权和生成的值2返回给调用函数——语句执行完毕后会给data赋值吧?或者等下一次给data赋值?,输出main: 2;
此时,生成器停在了这里;
再次执行next(mg)时,控制器又交给了xyz()函数,从上一次执行yield语句的下一句开始执行,于是,输出了“xyz 2, data = None”,上一次执行yield时,给data的值居然是None,孤以为会是2呢!
试验二:生成器的send函数和yield返回值语句的关系
1 def xyz():
2 print('xyz 0')
3 while True:
4 print('xyz 1')
5 data = yield 2
6 print('xyz 2, data = ', data)
7
8 if __name__ == '__main__':
9 print('main 0')
10 mg = xyz()
11 print('main 1')
12 mg.send(None) # 第一次必须如此!!!
13 print('main 2')
14 for _ in range(3):
15 print('\nmain 3')
16 mg.send(_)
17 print('main 4')
结果:
main 0
main 1
xyz 0
xyz 1
main 2
main 3
xyz 2, data = 0
xyz 1
main 4
main 3
xyz 2, data = 1
xyz 1
main 4
main 3
xyz 2, data = 2
xyz 1
main 4
介绍:
第一次必须执行mg.send(None),为什么这样孤还没搞清楚,和生成器的内部实现有关;
在调用send函数时,控制权交给xyz()函数,执行到yield语句停止,再将控制器返回给调用函数;
主函数中循环执行send函数;
第一次发送了0,结果输出xyz 2, data = 0,这里的data不是None了,即便之前有调用send(None),这是否可以认为,yield语句是在 控制权交给生成器所在函数后才执行的?
xyz()中的循环执行到print('xyz 1')再次停止,控制器返回给主函数;
之后再把1、2发送给生成器;
总结
next(generator), generator.send(data)都会将控制权交给生成器函数;
yield语句是在获取控制权后执行,而不是之前,之前程序挂在这里了,同时保存了上下文;
下面三条语句的解释:
yield # 返回给主调函数None
data = yield # 返回给主调函数None,并把send的值赋值给data;如果是使用next获取了控制权,那么,调用next处获得None;
data = yield 2 # 返回给主调函数next(),并把send的值赋值给data;