通过列表生成式,可以很方便的创建生成一个列表。但是当我们一次要创建一个一百万条数据的列表的时候,那么就会非常占用存储空间,所以如果列表元素可以按照某种算法推算出后续的元素,那么就可以节省很大的空间,这种一边循环一边计算的机制,成为生成器:generator
生成器可以使用next()方法来获取下一个元素,当获取完毕后再次获取会抛出可以用对象的__next__(),内置方法来获取生成器的值
生成器,只有在调用时才会生成相应的数据
创建一个generator,有很多办法:
1、利用列表生成式,创建生成器g
1 g = (x for x in range(10) )
2 >>> g
3 <generator object <genexpr> at 0x0344A480>
4 >>>
2、利用函数,创建生成器(yield)
生成器于普通函数不同的地方是,生成器利用yield返回,而函数利用return来返回
函数遇到yield关键字后,会直接返回,下次执行后,继续执行yield后面的代码,直到再次遇见yield后返回
1 >>> def test(): 2 n = 0 3 while n < 10: 4 yield n 5 n += 1 6 >>> test() 7 <generator object test at 0x0344A4B0>
例子:斐波那契序列:
1,1,2,3,5,8,13...... 前面的两个数相加等于第三个数,这就是著名的斐波那契序列.
1 2 def fib(num): 3 n,a,b=0,0,1 4 while n < num: 5 print(b) 6 a,b = b,a+b -->这里的原理是,预先 t = (b,a+b) ,然就在a=t[0],b=t[1] 7 n+=1 8 fib(6) 9
注意:
1、如果函数被改造成生成器,那么函数的return语句返回的将是异常提示信息,如果我们在生成器中return 'test',那么我们调用next()方法直到数据读取完毕后,会抛出StopIteration:test的异常!
2、生成器属于懒惰序列,如果不去循环的调用、或者使用next方法去获得元素,它是不会去加载后面的数据的,如果我们现在需要加载,那么可以通过list(),把生成器的数据转换成list输出即可。
1 def gen(): 2 q,n = 0,1 3 while q < 10: 4 yield n 5 n+=1 6 q+=1 7 print(list(gen()))