前言

一直对python中的yield关建字的作用一知半解,很多博客根本是照着官网翻译的… 知道看到这篇文章 🔗python中yield的用法详解🔗 才理解了其涵义,特此记录.

正文

yield与return及生成器

首先, yield是一个 “return”, 其次带有yield的函数是一个迭代器;
如下代码:

1
2
3
4
5
6
7
8
9
def foo():
print("starting...")
while True:
res = yield 4
print("res:",res)
g = foo() #因为yield存在,函数并未真正执行,即未输出任何字符串
print(next(g))
print("*"*20)
print(next(g))

运行结果:

1
2
3
4
5
starting...
4
********************
res: None
4

解释:

程序开始执行后,因为函数中存在yield关键字所以并不会真正执行,而是得到一个生成器g.

调用next方法,foo函数开始执行.

执行时遇到yield关建字,将其看成’return 4’,return后程序停止, res并没有被赋值,next(g)执行完成,结果即前两句.

程序执行print(“*”*20),输出20个*

再次调用next方法,程序从上次执行的中断处继续执行

从上次中断处执行(即res的赋值操作),时候要注意,这个时候赋值操作的右边是没有值的(因为刚才那个是return出去了,并没有给赋值操作的左边传参数) ,所以这个时候res赋值是None,所以接着下面的输出就是res:None.

程序会继续在while里执行,又一次碰到yield,这个时候同样return 出4,然后程序停止,print函数输出的4就是这次return出的4.

生成器中的send()函数

通过send方法来将一个值”发送“给生成器。other = yield foo 这样的语句的意思是,"返回foo的值,这个值返回给调用者的同时,将other的值也设置为那个值.

再看代码:

1
2
3
4
5
6
7
8
9
def foo():
print("starting...")
while True:
res = yield 4
print("res:",res)
g = foo()
print(next(g))
print("*"*20)
print(g.send(7))

结果:

1
2
3
4
5
starting...
4
********************
res: 7
4
  1. 同上…

  2. 程序执行g.send(7),程序会从yield关键字那一行继续向下运行,send会把7这个值赋值给res变量

  3. 由于send方法中包含next()方法,所以程序会继续向下运行执行print方法,然后再次进入while循环

  4. 程序执行再次遇到yield关键字,yield会返回后面的值后,程序再次暂停,直到再次调用next方法或send方法。

参考资料

🔗python中yield的用法详解——最简单,最清晰的解释🔗
🔗Python生成器及send用法讲解🔗