看了很多博客,都没有讲清楚。
首先yield关键字的功能与return完全相同,就是返回表达式的值。
当一个python函数中包含了yield关键字时,该函数就自动变成了一个生成器函数。生成器函数和普通函数的区别在于:
- 生成器函数在调用时不会执行;
- 生成器函数的执行可以通过函数 next() 和 func_name.send() 控制;
- 生成器函数是迭代器,可以迭代地生成yield返回的值。
话不多说,直接上案例:
我们以单步执行的方式解释以上代码的执行过程:
- 由于函数gen()函数包含了yield关键字,该函数识别为生成器函数;
- 第7行调用了gen(),但生成器函数在调用时不会执行,所以什么都没发生;
- 第8行将gen()传给了对象g;
- 第9行next(g)开始执行函数g,执行到第一次出现yield关键字为止,并返回yield后面的数值123;
- 第11行next(g)从上一次结束的地方继续执行函数g。这里要注意,由于数值123被yield返回了,因此对象result并没有被赋值,print(result)显示为None。由于在while循环中,函数g会执行至再次遇见yield关键字为止,并返回yield后面的数值123;
- 第13行调用了生成器函数的send()方法。这里数值456被传递给上次停止时yield关键字的位置,于是对象result被赋值,print(result)显示为456。由于send()方法包括了next(),于是函数g会执行至再次遇见yield关键字为止,并返回yield后面的数值123。
通过以上解释,yield关键字的作用非常清楚了:其功能就是类似return关键字,返回其后的表达式。同时yield担任了截断点,用户可通过next()函数控制生成器函数在相邻截断点间的执行过程。因此,生成器函数的定义体中通常都有循环,next()函数控制循环进程,send()函数负责更新循环体内对象的取值。
上面也提到,生成器函数也是迭代器,于是我们就可以像正常迭代器一样使用它,yield关键字负责返回取值,如下所示: