day4-生成器并行运算
概述
之前只是介绍生成器,那有些同学就说了,这个生成器除了能节省资源,提高工作效率,但是我们再哪些场景下可以用呢?在哪些地方可以体现出它的价值呢?下面我们来逐一解答这些疑问。
生成器执行过程
程序执行过程
def consumer(name): print("%s准备发工资啦!"%name) while True: gongzi=yield print("工资%s来了,被%s领了!"%(gongzi,name)) x=consumer("huwei") x.__next__() #输出 huwei准备发工资啦!
我们再加几个__next__()方法:
def consumer(name): print("%s准备发工资啦!"%name) while True: gongzi=yield print("工资%s来了,被%s领了!"%(gongzi,name)) x=consumer("huwei") x.__next__() x.__next__() b="1个亿" x.send(b) x.__next__() #输出 huwei准备发工资啦! 工资None来了,被huwei领了! 工资1个亿来了,被huwei领了! 工资None来了,被huwei领了! # next()只是在调用(唤醒)yield,但是不会给其传值,而send除了能够调用(唤醒)同时还能给其传值
第一个例子没有执行print("工资%s来了,被%s领了!"%(gongzi,name)),接着我们来调试一下,看看具体过程:
...........................debug
yield实现串行下的并行效果
我们把"优化"发工资的再规范一下,可以使用
#-*-coding:utf-8-*-
import time
def consumer(name): #0
print("%s准备发工资啦!"%name) #4
while True:
gongzi=yield #5
print("工资%s来了,被%s领了!"%(gongzi,name)) #9
def producer(name):
x=consumer("A") #1 只是将consumer()变成一个生成器
x1=consumer("B") #2 只是将consumer()变成一个生成器
x.__next__() #3
x1.__next__() #6
print("财务开始做工资啦!") #7
for i in range(10):
time.sleep(2)
print("做了2个人的工资!")
x.send(i) #8
x1.send(i) #10
producer("dick")
#输出
A准备发工资啦!
B准备发工资啦!
财务开始做工资啦!
做了2个人的工资!
工资0来了,被A领了!
工资0来了,被B领了!
做了2个人的工资!
工资1来了,被A领了!
工资1来了,被B领了!
做了2个人的工资!
工资2来了,被A领了!
工资2来了,被B领了!
解析:在#1和#2只是将consumer()函数变成生成器(如果# 0 consumer是函数的话,我们执行consumer()就会直接打印),在这里#0是生成器,而我们第一次调用#3目的是要其打印#4,我们执行#3时,程序consumer才会继续往下执行,执行到#5处 自动中断返回,返回到#6,再从#6调用程序consumer会继续往下执行,执行到#5处 自动中断返回到#7继续向下执行,当执行到#8时将#8 I 的值赋值给yield,继续向下#9执行,执行后由于是while循环,又继续回到#5跳出返回到#10,接着#10又send I 赋值给#5,如此运行,直到结束
注意:实现单线程下的并行处理,虽然它仍然是串行依次处理,但是我们可以在不同的角色之间来回地切换,并且运行速度特别快,感觉上是并行的。注意,这个就是异步I/O的雏形。