1.列表生成式
经过列表生成式,能够直接建立一个列表,可是受内存限制,列表容量有限,并且建立的列表太大,占用存储空间
a = [i*2 for i in range(10)] print(a) #[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
2.生成器
定义:经过某种算法将列表推算出来,不用建立完整的list,节省大量内存空间,这种一边循环一边计算的机制,称做生成器,generator
特色:只有在调用的时候才产生数据,不会象列表同样先将全部数据加载到内存;只记录当前位置,不会象列表同样记录全部数据下标;只有一个方法__next__
2.1将列表生成式转化为生成器
b = (i*2 for i in range(10)) #将一个列表生成式转化生成器只须要将[]-->() print(b) #<generator object <genexpr> at 0x00492870> for i in b: #经过循环调用生成器中数据 print(i) if i > 5: #若是在循环中终断程序,会接着调用生成器中的数据 break print(b.__next__()) print(b.__next__()) #经过__next 方法一个个调用生成器中数据 print(b.__next__()) print(b.__next__()) print(b.__next__())
2.2经过函数实现生成器python
斐波那契数列:除第一个和第二个数以外,任意一个数均可以由前两个数相加获得:
1,1,2,3,5,8,13,21,34...........
用函数实现斐波那契数列以下:
def fib(max): n,a,b = 0,0,1 while n < max: print(b) a,b = b,a+b #注:a,b = b,a+b 至关于t = (b,a+b) a=t[0] b=t[1] n = n + 1 return "done" fib(10)
将上面函数变成生成器,只要把函数中的print(b)改为yeild 便可:
def fib(max): n,a,b = 0,0,1 while n < max: #print(b) yield b #当程序执行到yield会中断,直到下次调用接着执行 a,b = b,a+b #注:a,b = b,a+b 至关于t = (b,a+b) a=t[0] b=t[1] n = n + 1 return "--done--" print(fib(10)) <generator object fib at 0x00572870>
生成器调用:算法
f = fib(10) for i in f: #使用for循环调用生成器数据 print(i) print(f.__next__()) #使用__next__调用 print(f.__next__()) #因为生成器会记录当前位置,这个时候中止生成器去干别的,下次会接着执行 print("----------------") print(f.__next__()) print("-----------------")
使用__next__方法调用生成器数据超过指定的范围出现报错,报错信息:StopIteration: --done--
可使用如下方法执行该生成器,将这个报错信息抓出正常返回:
while True: try: x = f.__next__() print("f:",x) except StopIteration as e: print("generator return value",e.value) break
3.生成器实现单线程下的并行效果,生产者消费者模型ide
import time def consumer(name): print("%s 开始准备吃包子"%(name)) while True: baozi = yield #每调用一次生成器,每次在执行到yield的时候会跳出,直到下次调用接着执行 print("包子%s来了,被%s吃了"%(baozi,name)) def produer(name): c1 = consumer("A") #consumer是生成器,将其赋值给c1,c2 当用__next__方法调用时,c1和c2分别执行到yield跳出继续执行produer函数 c2 = consumer("B") c1.__next__() #执行consumer这个生成器,当执行到yield时中断跳出 c2.__next__() #执行consumer这个生成器,当执行到yield时中断跳出 print("开始作包子了") for i in range(10): time.sleep(1) c1.send(i) #__next__只是在调用yield,而send在调用的同时还会给yield传值 c2.send(i) # produer("cx") #注:若是是函数直接consumer("A") 就会执行,但有yield以后就变成生成器,必须使用循环,或者next方法调用才会执行