生成器(generator)是迭代器(iterator)的一种,不同于列表解析[x for x in iterator]会直接在内存中生成整个列表;generator保存的是算法,并用()代替[],直接打印会显示类似<generator object <genexpr> at 0x000001CF97AFDB10>的输出,并且用next()函数获得generator的下一个返回值。

生成器有两种方法产生:

一种是()括起来的generator表达式:

>>> (x for x in range(1,10))
<generator object <genexpr> at 0x000001CF97AFDB10>

一种是含有yield的函数:

def fab(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        # print b
        a, b = b, a + b
        n = n + 1
>>> fab(3)
<generator object fab at 0x000001CF97DD5CF0>

这里额外做一个小总结:

  • 实现了iter()方法的对象是可迭代的(Iterable),可用于for()循环
  • 实现了next()方法的对象是迭代器(Iterator),可用next()迭代。

python中可以直接作用于for循环的有两类:

  • 集合数据类型 (listtupledictsetstr)
  • generator (包括以上介绍的enerator表达式和含有yield的函数)

集合数据类型(listtupledictsetstr),是Iterable(可迭代)但不是Iterator(迭代器):

>>> from collections.abc import Iterable
>>> from collections.abc import Iterator
>>> isinstance('abc',Iterable)
True
>>> isinstance('abc',Iterator)
False

这是因为python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list等是永远不可能存储全体自然数的。

generator既是Iterable(可迭代)也是是Iterator(迭代器):

>>> from collections.abc import Iterable
>>> from collections.abc import Iterator
>>> isinstance(fab(3),Iterable)
True
>>> isinstance(fab(3),Iterator)
True