python学习,day4:生成器,通过yield实现单线程情况下的并发运算
首先了解一个斐波那契函数的实现,了解下生成器的工作流程
1 # coding=utf-8 2 # Author: RyAn Bi 3 def fib(max): 4 n,a,b=0,0,1 5 while n < max: 6 #print(b) 7 yield b #定义一个生成器,也是个断点,每次运行都会再此调用 8 a,b = b,b+a 9 n = n +1 10 return 'done' 11 f=fib(2) 12 while True: 13 try: #定义一个异常处理 14 x= next(f) #运行下一步 15 print('f:',x) 16 except StopIteration as e: #处理异常,当运行到return的时候会进行下一步 17 print('Generator return value:',e.value) 18 break
其中,了yield关键字的核心用法,即逐个生成。在这里获取了两个生成器产生的值,即0和1。分别由next函数和send()函数获得
第一次调用__next__函数的时候,我们从生成器函数的起点开始,然后在yield处结束,需要注意的是,赋值语句不会调用,此处yield i和含义和return差不多。
但是第二次调用__next__函数的时候,就会直接从上一个yield的结束处开始,也就是先执行赋值语句,然后输出字符串,进入下一个循环,直到下一个yield或者生成器结束
再次看初始的那段代码,可以发现第二次调用的时候没有选择使用__next__函数,而是使用了一个sent()函数。这里就需要注意,sent()函数的用法和__next__函数不太一样。sent()函数只能从yield之后开始,到下一个yield结束。这也就意味着第一次调用必须使用__next__函数。
看下面的例子
1 def consumer(name): 2 print('%s要吃包子了'%name) 3 while True: 4 baozi =yield 5 print('包子%s来了,要被%s吃了!'%(baozi,name)) 6 7 c =consumer('bb') 8 c.__next__() 9 c.send('韭菜馅') 10 c.__next__()
用send给包子赋值
1 # coding=utf-8 2 # Author: RyAn Bi 3 import time 4 5 def consumer(name): 6 print('%s要吃包子了'%name) 7 while True: 8 baozi =yield 9 print('包子%s来了,要被%s吃了!'%(baozi,name)) 10 11 # c =consumer('bb') 12 # c.__next__() 13 # c.send('韭菜馅') 14 # c.__next__() 15 16 def producer(name): #制造包子 17 c = consumer('A') 18 c1 = consumer('B') #c和c1达到并行的效果,利用生成器 19 c.__next__() 20 c1.__next__() 21 print('a老子要吃包子了') 22 for i in range(10): 23 time.sleep(1) 24 print('做了2个包子') 25 c.send(i) 26 c1.send(i) 27 producer('bb')