列表生成式
什么是列表生成式,我们先举个栗子:
a = [1,2,3,4,5]
上面的语句创建一个列表,列表也可以通过下面的方法创建
a = [i*2 for i in range(10)] print(a) [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
第二种方法比第一种方法更加灵活。第二种方法就叫做列表生成式。
但是不管用哪种方法,列表中的元素都都是在列表创建的同时就被放在列表中了,如果有一个100万个数据的列表,就算我们只用第一个数据,后面的所有数据也会占用空间,造成空间浪费。有没有什么方法避免这种情况发生呢,答案是肯定的。方法就是生成器。
生成器就是把列表生成式的[ ]换成( )
a = (i*2 for i in range(10)) print(a) <generator object <genexpr> at 0x0000018B2FC65BC8>
现在a 就是一个生成器
我们现在要获取a中的数据
a = (i*2 for i in range(10))
print(a[0])
File "D:/7_Python/S14/Day4/生成器.py", line 3, in <module>
print(a[0])
TypeError: 'generator' object is not subscriptable
我勒个去,报错了,没法获得数据,这是为什么呢?
原因很简单,生成器与列表不同,上面我们说过,列表中的数据在列表创建的同时就已经被放到列表中了,因此我们可以获得数据
a = [1,2,3,4,5,6,7,8] print(a[3]) 4
但是生成器则不同,我们创建生成器的时候,只是创建了生成器本身,这是数据并没有被生成,所以我们不能像获取列表中的数据一样获取生成器中的数据
那我们该怎么获取生成器的数据呢?
使用__next__()方法就可以了
a = (i*2 for i in range(10)) print(a.__next__()) print(a.__next__()) print(a.__next__()) print(a.__next__()) 0 2 4 6
数据得到了。
但是要注意一点,生成器只保存当前的数据,也就是说我们获得6之后,只能向后在获得8,不能向前获得4这个数值
一般获得生成器的数值使用loop方法
a = (i*2 for i in range(10))
for i in a:
print(i)
0
2
4
6
8
10
12
14
16
18
实际使用生成器时,我们基本不会使用next函数获取数值,通常都会使用for循环来获取数据
下面这段是斐波那契函数
def fib(max):
n,a,b = 0,0,1
while n < max:
#print(b)
yield (b)
a,b = b,a+b
n += 1
return 'done'
f = fib(10)
print(f)
<generator object fib at 0x000002109B5D5AC8>
其中print被yield代替,这样fib()就不是函数了,而是一个生成器了