Python生成器(generator)--yield的使用

文章目录

前言

在 Python 中,使用了 yield 的函数被称为生成器(generator)。

跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。

在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。

调用一个生成器函数,返回的是一个迭代器对象。

一、yield是什么?

  • 可以把yield看成和return类似的返回值。但yield又和return有很大不同之处。
  1. yield与return的相同之处:
    都是在函数中第一次遇见yield/return就返回其后面的值。
  2. yield与return不同之处:
    1.带有yield的函数不再是一个普通的函数,而是一个生成器(generator)。用于迭代
    2.与带有return的普通函数不同。调用带有yield的函数(生成器)时不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。即用的时候(迭代时)才生成。
    3.yield 是一个类似 return 的关键字,每迭代一次遇到yield时就返回yield后面的值。重点是:下一次迭代时,从上一次迭代遇到的yield后面的代码开始执行。第一次调用时必须先next(),否则会报错。

生成器(generator):可以看成一个能够迭代的list。可以执行next()函数,直到捕获到第一个异常后终止(即迭代完所有元素)。
谷歌解释:所谓生成器函数, 就是每当它执行一次生成(yield)语句, 它就返回一个迭代器, 这个迭代器生成一个值. 生成值后, 生成器函数的运行状态将被挂起, 直到下一次生成.
注:在for … in …中默认会执行next()函数。

yield的优点

1.节省内存,运算速度快
通常的for…in…循环中,in后面是一个数组,这个数组就是一个可迭代对象,类似的还有链表,字符串,文件。它可以是list = [1, 2, 3]等。 但它的缺陷是所有数据都在内存中,如果有海量数据的话将会非常耗内存。
而生成器(generator)是可以迭代的,但只可以读取它一次。因为用的时候才生成。比如 range(3),注意这里用到了range(),它就不是数组,只有每次用到才调用,而上面的例子是[]。

简要理解:yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后开始。
带有yield的函数不仅仅只用于for循环中,而且可用于某个函数的参数,只要这个函数的参数允许迭代参数。比如array.extend函数,它的原型是array.extend(iterable)。

代码示例

def yield_test1(n):  
    while n>0:           
        yield n   
        n=n-1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
a = yield_test1(4)
print(next(a))
print(next(a))
print(next(a))
print(next(a))
#尝试在多加一个print(next(a)),则会报错。因为无法满足迭代条件。
Output:
4
3
2
1

总结

一个带有 yield 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,并返回一个迭代值,下次执行时从 yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。

yield 的好处是显而易见的,把一个函数改写为一个 generator 就获得了迭代能力,比起用类的实例保存状态来计算下一个 next() 的值,不仅代码简洁,而且执行流程异常清晰。

参考文章

Python yield使用浅析
彻底理解python中的yield

上一篇:mybatis-generator自动生成代码(减少sql的xml)


下一篇:MyBatis三剑客