生成器详解

来源:互联网 发布:删除json里的一个对象 编辑:程序博客网 时间:2024/06/01 08:12

可迭代对象(iterable) 与 迭代器(iterator)

关系如下图:

这里写图片描述

对一个iterable用for … in …进行迭代时,实际是先通过调用iter()方法得到一个iterator,假设叫做X。然后循环地调用X的next()方法取得每一次的值,直到iterator为空,返回的StopIteration作为循环结束的标志。for … in … 会自动处理StopIteration异常,从而避免了抛出异常而使程序中断。


生成器

生成器,就是带有yield的函数。包含生成器函数和生成器表达式(形如(elem for elem in [1, 2, 3])的表达式)

生成器函数(generator function)的返回值是生成器、迭代器(generator iterator)
生成器表达式(generator expression)的返回值是迭代器(iterator)

示例代码如下:

>>> a = (elem for elem in [1, 2, 3])>>> a<generator object <genexpr> at 0x7f0d23888048>>>> def fib():...     a, b = 0, 1...     while True:...         yield b...         a, b = b, a + b...>>> fib<function fib at 0x7f0d238796a8>>>> b = fib()<generator object fib at 0x7f0d20bbfea0>

综上:生成器(generator)就是迭代器(iterator)的一种,以更优雅的方式实现的iterator,而且完全可以像使用iterator一样使用generator。当然除了定义,定义一个iterator,你需要分别实现_ _ iter _ _ ()方法和 _ _ next_ _()方法,但generator只需要一个小小的yield

生成器的调用方法:
示例代码:

>>> def gen():...     while True:...         s = yield...         print(s)...>>> g = gen()>>> g.send("kissg")Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: can't send non-None value to a just-started generator>>> next(g)>>> g.send("kissg")kissg

从上述例子可以看出,generator 其实有2种调用方法(恢复执行),即通过send(value)方法将value作为yield表达式的当前值。你可以用该值再对其他变量进行赋值。当我们调用send(value)方法时,generator正由于yield的缘故被暂停了。此时,send(value)方法传入的值作为yield表达式的值,函数中又将该值赋给了变量s,然后print函数打印s,循环再遇到yield,暂停返回。

调用send(value)时要注意,要确保 generator 是在yield处被暂停了,如此才能向yield表达式传值,否则将会报错(如上所示),可通过next()方法或send(None)使generator执行到yield。

再来看一段yield更复杂的用法,或许能加深你对generator的next()与send(value)的理解。

>>> def echo(value=None):...   while 1:...     value = (yield value)...     print("The value is", value)...     if value:...       value += 1...>>> g = echo(1)>>> next(g)1>>> g.send(2)The value is 23>>> g.send(5)The value is 56>>> next(g)The value is None

小结

这里写图片描述

  1. 可迭代对象(Iterable)是实现了iter()方法的对象,通过调用iter()方法可以获得一个迭代器(Iterator)。
  2. 迭代器(Iterator)是实现了iter()和next()的对象。
  3. for … in …的迭代,实际是将可迭代对象转换成迭代器,再重复调用next()方法实现的。
  4. 生成器(generator)是一个特殊的迭代器,它的实现更简单优雅。
  5. yield是生成器实现next()方法的关键。它作为生成器执行的暂停恢复点,可以对yield表达式进行赋值,也可以将yield表达式的值返回。

参考文档:http://kissg.me/2016/04/09/python-generator-yield/

1 0
原创粉丝点击