python 基础——generate生成器
通过列表表达式可以直接生成列表,不过列表一旦生成就需要为所有元素分配内存,有时候会很消耗资源。
所以,如果列表元素可以按照某种算法推算出来,这样就不必创建完整的list,从而节省大量的内存空间。
在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。
创建列表
法一: test = range(10) print type(test) # <type 'list'> 法二: test = [item for item in range(10)] print type(test) # <type 'list'>
创建生成器
test = (item for item in range(10)) print type(test) # <type 'generator'>
生成器是一个可以自动推导后续元素的对象,为了得到其元素,我们可以直接通过 next() 方法:
test = (item for item in range(10)) print type(test) print test.next() print test.next() print test.next() # <type 'generator'> # 0 # 1 # 2
另外一种方式是用 for 可以直接迭代生成器的所有元素:
test = (item for item in range(10)) print type(test) for item in test: print item # <type 'generator'> # 0 # 1 # 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9
注意,每一次调用 next() 都使得生成器推导出下一个元素,使得生成器的元素减少:
test = (item for item in range(10)) print type(test) print test.next() print test.next() #至此,生成器中只还有8个元素 for index, item in enumerate(test): print index, '=', item # <type 'generator'> # 0 # 1 # 0 = 2 # 1 = 3 # 2 = 4 # 3 = 5 # 4 = 6 # 5 = 7 # 6 = 8 # 7 = 9
用函数创建生成器
如果函数中包含 yield ,那么该函数就变成了一个生成器。
函数类型的生成器的特点是:在每次调用 next() 的时候执行,遇到 yield 语句就完成一个元素的推导并返回,再次执行 next() 时从上次返回的 yield 语句处继续向后执行:
def func(): def func(): print 'one' print 'one' yield 1 yield 1 print 'two' print 'two' yield 2 yield 2 print 'three' print 'three' yield 3 yield 3 test = func() test = func() test.next() test.next() test.next() test.next() for item in test: for item in test: print item item # one # one # two # two # three # three # 3 # 此时并没有打印生成器的最后一个元素值
生成器函数应用示例
用生成器产生斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
直接打印元素:
def func(max): before = 0 after = 1 while after < max: print before before, after = after, before + after func(10) # 0 # 1 # 1 # 2 # 3 # 5
使用列表保存结果:
def func(max): list = [] before = 0 after = 1 while after < max: list.append(before) before, after = after, before + after return list my_list = func(10) print my_list # [0, 1, 1, 2, 3, 5]
使用生成器:
def func(max): before = 0 after = 1 while after < max: yield before before, after = after, before + after test = func(10) print test for item in test: print item # <generator object func at 0x7f228e111730> # 0 # 1 # 1 # 2 # 3 # 5