通过列表生成式我们可以方便的生成列表。但是在有的时候,我们需要生成的列表非常长,而我们的计算机的内存是有限的。在操作列表的时候,我们往往只是操作了列表的一部分区域的数据。
例如我们需要生成这么一个列表,列表中除了第1个和第2个数字外,其余数字都是前两个数之和。
1,2,3,5,8,13...
如果这个数组只有几千个或者几万个数字的时候,我们或许还能将它们都生成存在内存中。但是我们如果需要连续计算几千万个数字的时候,我再按上面的思路来就不大现实了。
认真思考一下上面的数列,我们在遍历的时候,其实只要知道前两个数字的数值,我们就能源源不断地计算出下一个数值是多少。
Python其实已经给我们提供了现有的工具让我们生成数列。与之前的生成式不同,生成器(Generators)在定义的时候并不是直接在内存中生成数列,而是定义一个生成数列的算法。
定义列表生成器有两种方式,一种是算式列表生成器(我起的名字),一种通过yield
关键词。
算式列表生成器
算式列表生成器雨列表生成式类似,但[]
需要换成()
。
my_gernerator = (x*x for x in range(1,101))
generator object的迭代方式
1. next()函数
我们可以调用generator object的next()函数让指针下移。例如
print my_generator.next() #输出 1
print my_generator.next() #输出 4
print my_generator.next() #输出 9
每调用一次next()
,计算出一个值,并记忆迭代到何处了。当迭代到最后一个元素后再调用next()
,python则会抛出StopIteration
错误。我们可以捕获这个错误来处理迭代终止。next()
这种手动调用的运用较少。
2. 用for循环
我们可以利用collections.Iterable
来判断generator object
是否是一个Iterable
对象。
from collections import Iterable
g = (x**3 for x in range(1,101))
print isinstance(g, Iterable) #输出True
因此我们可以用for
迭代generator object
。
for item in g:
print item
包含yield
的函数定义列表生成器
在定义一个比较复杂的列表生成器的时候,上述算式型的列表生成器已经不能满足我们的需求了。我们可以用一个包含yield
关键字的函数来定义一个列表生成器。
例如我们来实现一下文章开头生成一个“每个数字都是前两个数字之和”的数列。
def fibonacci(max):
n,a,b = 0,1,2
while n<max:
yield b #-----> Generator迭代到该处时,即产生一个数。并暂停在此处,等待下一次迭代,又从该处开始,又直到遇到下一个yield..不断反复,直到程序结束。
a,b = b,a+b
n = n+1
此时,fibonacci
不再是一个普通函数,而是一个generator object
。
我们通常用for
循环来迭代generator
对象。
for n in fibonacci(10):
print n
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。