标签:python生成器
python生成器
为什么用生成器?
列表生成式: 使代码更简洁、还可以执行一个函数;
[i*2 for i in range(10)]
生成 :[0,2,4,6,8,12,14,16,18]
[i*2 for i in range(10)]
相当于以下三句代码:
a = []
for i in range(10):
a.append(i*2)
通过列表生成式,我们可以直接创一个列表。但是受到内存限制,列表容量肯定是有限的。而且创建一个包含100万个元素的列表,
不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那么后面绝大多数元素占用的空间是白白浪费的。
生成器定义
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,
从而节省大量的空间。在python中,这种一边循环一边计算的机制,称为生成器:generator。
生成器创建方法
要创建一个generator,有很多种方法。
第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:
生成器内容深化
生成器被调用的时候才生成所以列表元素
a = (i*2 for i in range(10)) #生成器 print(a) <generator object <genexpr> at 0x00000212699D1E08>
例如:访问前两个数据
a = (i*2 for i in range(10)) print(a.__next__()) print(a.__next__())
生成器只记录当前位置,只存储一个数据;
只有一个__next__()方法。在python2.0 里边是next()
取数据可以用for循环取数据;
当推算的算法比较复杂的时候,用for循环无法实现的时候,用函数来实现。
fib例子:
先看一下斐波那契数列Fibonacci简写fib,除了第一个和第二个数外,任意一个数都可以由前两个数相加得到;
如: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 n = n+1 return ‘done‘ #10代表生成10个斐波那契数据,从1开始。 fib(10)
注意:赋值语句
a,b = b,a+b 相当于: t = (b,a+b) #t是一个tuple a = t[0] b = t[1]
上面的函数和generator仅一步之遥,只需要把print(b)改成yield b 就可以了:
def fib(max): n,a,b = 0,0,1 while n < max: yield b a,b = b,a+b n = n+1 return ‘done‘ #print(fib(10)) f = fib(10) print(f.__next__()) print(f.__next__()) print(f.__next__()) for i in f: print(i)
当f.__next__取到第11个数据的时候,已经没有数据了,程序会报出一个错误done;
如果不想报错,就抓住这个异常。
def fib(max): n,a,b = 0,0,1 while n < max: yield b #保存了中断状态,反悔了当前的状态值; a,b = b,a+b n = n+1 return ‘--done--‘ #作用是异常的时候打印这个消息 #print(fib(10)) f = fib(3) #以下为异常处理代码 while True: try: x = next(f) print("f:",x) except StopIteration as e: print("generaotr return value:",e.value) break print(f.__next__()) print(f.__next__()) print(f.__next__()) print(f.__next__())
通过装饰器可以实现并行效果,使单线程也可以并发。
通过yield实现在单线程的情况下实现并发运算的效果。
例子:典型的生产者消费者模型
import time #消费者 def consumer(name): #consumer 消费者 print("%s 准备吃包子啦!"%name) while True: baozi = yield print("包子[%s]来了,被[%s]吃了!"%(baozi,name)) c = consumer("123") #只是变成一个生成器,而不执行;如果是函数是会被调用的。 c.__next__() #调用 # c.__next__() c.send("韭菜") def producer(name): c = consumer("A") c2 = consumer("B") c.__next__() c2.__next__() print("开始准备吃包子啦!") for i in range(3): time.sleep(1) print("做了1个包子,分两半!") c.send(i) c2.send(i) producer("abc")
这个是一个最简单的协程;协程比线程更小的一个单位;
本文出自 “506554897” 博客,请务必保留此出处http://506554897.blog.51cto.com/2823970/1963775
标签:python生成器
原文地址:http://506554897.blog.51cto.com/2823970/1963775