您的位置:首页 > 其它

生成器详解

2017-04-23 19:17 113 查看

可迭代对象(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 2
3
>>> g.send(5)
The value is 5
6
>>> next(g)
The value is None


小结



可迭代对象(Iterable)是实现了iter()方法的对象,通过调用iter()方法可以获得一个迭代器(Iterator)。

迭代器(Iterator)是实现了iter()和next()的对象。

for … in …的迭代,实际是将可迭代对象转换成迭代器,再重复调用next()方法实现的。

生成器(generator)是一个特殊的迭代器,它的实现更简单优雅。

yield是生成器实现next()方法的关键。它作为生成器执行的暂停恢复点,可以对yield表达式进行赋值,也可以将yield表达式的值返回。

参考文档:http://kissg.me/2016/04/09/python-generator-yield/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  生成器模式