普通遍历
for i in range(1,10000):
pass
生成器遍历
for i in xrange(1,10000):
pass
这个函数会 yield
很多值而不是只返回一个。这就让一个看上去很普通的函数 转变成一个生成器,一种可以被重复轮询下一个可用值的函数。
首先要注意的是 range 的实现必须预先创建一个列表保存范围内的所有数字。所
以,如果范围从 1 到 10000,这个函数会对 numbers 列表进行 10000 次 append (在第 3 章我们已经讨论过这部分开销),然后返回整个列表。而另一方面,生成器 则能够“返回”很多值。每次代码运行到 yield,该函数都会发射出一个值,然 后当外部代码需求另一个值时,该函数才会继续运行(之前的状态保持不变)并发 射新的值。当该函数运行结束时,一个 StopIteration 异常会被抛出表明该生
成器已经没有更多的值了。结果就是,虽然两个函数最终运行了同样的计算次数, 使用 range 版本的循环多消耗了 10000 倍的内存(如果范围从 1 到 N 则是 N 倍)。
我们主要关注标准库中的 itertools 库。它提供了 Python 内建函数 map、reduce、 filter 和 zip 的生成器版本(在 itertools 中分别是 imap、ireduce、ifilter 和 izip),以及其他很多有用的函数。特别值得注意的有:
islice
允许对一个无穷生成器进行切片。
chain
将多个生成器链接到一起。
takewhile
给生成器添加一个终止条件。
cycle
通过不断重复将一个有穷生成器变成无穷。