这篇文章是对上一篇讲生成器和迭代器的文章做的补充。
回顾一下概念,什么是生成器?
生成器就是一个包涵yield关键字的函数,当这个函数被调用的时候,函数体中的代码不会被执行!
而是返回了一个迭代器。
每请求一个值,就回执行一次生成器中的代码,直到遇到yield或者return。
其中yield意为着生成一个值,而return意为着生成器要停止执行,不再生成任何东西,这是yield和return本质上的区别。
其实函数式生成器,可以当做是分文两部分组成的,生成器的函数和生成器的迭代器。
下面是关于生成器常用方法详解:
next()老生常谈,没什么好说的了,从生成器中获取一个新的值,这个值是从生成器的yeild中返回出来的。
send() 和next方法作用很相似,都可以从生成器中取一个值,和next不同的是,send方法可以给yield传值,然后在通过yield传递给生成器中的变量,也就是间接的给生成器内部的变量赋值(通过下面的例子可以看到)
注意!!在使用send方法有一个特别的注意事项!就是第一次调用生成器时,请使用next方法或者是send(None)send一个空值,如果send其他的值会出错!!这是因为没有yield语句去接收这个值!
(简单的说,就是在函数的执行状态被“挂起”send方法才会起到相应的作用。)
最后,在细说下前面写的那个简化版的“生产者与消费者”模型。
1 import time
2 def consumer(name):
3 print ‘我是%s,准备开始吃包子了‘%(name)
4 while True:
5 stuffed_bun = yield
6 time.sleep(1)
7 print "%s很开心的把%s吃掉了" %(name,stuffed_bun)
8 def producer():
9 p1 = consumer("suhaozhi")
10 p2 = consumer("ayumi")
11 p1.next() #执行next方法后,死循环开始
12 p2.next()
13 for i in range(10):
14 time.sleep(1)
15 p1.send("包子%s" %(i)) #通过send给yield赋值,yield在将值赋给stuffed_bun
16 p2.send("包子%s" %(i))
17 producer()
首先,第一步开始执行producer生产者函数,这个函数使用生成器生成了两个“消费者”,首先要明确一个概念!!其中第9行和第10行,只是定义了两个生成器,并不会执行consumer函数中的任何内容。
定义好了两个生成器之后,11行和12行执行的next方法,启动这两个生成器,这时,回到consumer函数,开始执行死循环,执行到yield时候开始将执行状态“挂起”准备接收producer函数(生产者)传的值。
15行16行的代码,就是将值传递给consumer函数中的yield对应的stuffed_bun变量,当yield收到了来15,16行的send方法传递值后,执行第6行和第7行,然后回到producer函数的for循环然后继续执行15行和16行的代码,继续通过yield接收send方法发来的值,给stuffed_bun这个变量赋值....一直到producer(生产者)中的for循环执行结束。