列表生成式
什么是列表生成式,我们先举个栗子:
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()就不是函数了,而是一个生成器了
说明一点,上面代码中a,b = b,a+b的意思是
t = (b,a+b) a = t[0] b = t[1]
生成器可以完成一些并发的事务
import time def consumer(name): print(‘客人%s准备吃包子了‘ %name) while True: baozi = yield print(‘包子[%s]被%s吃了‘ %(baozi,name)) def producer(name): c1 = consumer(‘vivian‘) c2 = consumer(‘maluko‘) c3 = consumer(‘mogu‘) c1.__next__() c2.__next__() c3.__next__() print(‘%s准备做包子了‘ %name) for i in range(10): time.sleep(1) print(‘%s做了三个包子‘ %name) c1.send(i) c2.send(i) c3.send(i) producer(‘hanchao‘)
原文:https://www.cnblogs.com/goldtree358/p/11647551.html