A.创建一个生成器
1.列表生成式的[]变成()
g = (x * x for x in range(10)) print(g.__next__()) print(g.__next__()) print(g.__next__())
generator保存的是算法,每次调用next(),就会计算出g的下一个值,直到最后一个值计算出来
g = (x * x for x in range(10)) for x in g: print(x)
生成器是可迭代对象
2.函数实现
函数中的return改成yield即可
def odd(): print('step 1') yield 1 print('step 2') yield(3) print('step 3') yield(5) o=odd() next(o) o.__next__() next(o)
def odd(): print('step 1') yield 1 print('step 2') yield(3) print('step 3') yield(5) o=odd() t=next(o) print(t) t=o.__next__() print(t) t=next(o) print(t)
B.generator的send()函数和yield关键字
yield关键字 的作用是 函数与调用者的通信,它不光能够将值返回给调用者,它还可以接收调用者传过来的值,那么怎么实现呢? 调用者通过send()函数将值传递给generator,generator通过 yield 前面的变量来接收,如下:
但其实 yield关键字 的作用是 函数与调用者的通信,它不光能够将值返回给调用者,它还可以接收调用者传过来的值,那么怎么实现呢? 调用者通过send()函数将值传递给generator,generator通过 yield 前面的变量来接收,如下:
send函数和next函数的区别就是 send函数可以在执行generator的过程中,给generator发送消息。而next仅仅是接收yield右边的变量值。
生产者消费者模型
import time def consumer(name):#消费者吃包子 print('我是[%s],我准备开始吃包子了' %name) while True: baozi=yield time.sleep(1) print('%s 很开心的把【%s】吃掉了' %(name,baozi)) def producer():#生产包子 c = consumer('wupeiqi') c.__next__()#执行到了循环的第一个yield,把第一句话打印出来了 for i in range(5): time.sleep(1) c.send('包子 %s' %i) producer()
send函数与yield关键字配合使用可以实现调用者与generator的通信了,那么我们就可以通过他们来实现单一线程切换执行不同函数了。这种操作就叫做协程。
C.生成器只能遍历一次
def test(): for i in range(3): yield i t = test() for i in t: print(i) t1=(i for i in t)#这个循环会执行,但是t已经遍历完了,现在什么都没有 print(list(t1))#所以会输出一个空列表
def test(): for i in range(3): yield i t = test() t1=(i for i in t) t2=(i for i in t1) print(list(t1))#list是在遍历t1 print(list(t2))#t1被list遍历过以后,已经不能被遍历了
def test():
for i in range(3):
yield i
t = test()
t1=(i for i in t)
t2=(i for i in t1)
print(list(t1))#list是在遍历t1
print(list(t2))#t1被list遍历过以后,已经不能被遍历了