对于普通的生成器,第一个next
调用,相当于启动生成器,会从生成器函数的第一行代码开始执行,直到第一次执行完yield
语句(第4行)后,跳出生成器函数。
然后第二个next
调用,进入生成器函数后,从yield
语句的下一句语句(第5行)开始执行,然后重新运行到yield
语句,执行后,跳出生成器函数,
后面再次调用next
,依次类推。下面是一个列子:
def consumer():
r = 'here'
for i in xrange(3):
yield r
r = '200 OK'+ str(i)
c = consumer()
n1 = c.next()
n2 = c.next()
n3 = c.next()
了解了next()
如何让包含yield
的函数执行后,我们再来看另外一个非常重要的函数send(msg)
。其实next()
和send()
在一定意义上作用是相似的,区别是send()
可以传递yield
表达式的值进去,而next()
不能传递特定的值,只能传递None
进去。因此,我们可以看做c.next()
和 c.send(None)
作用是一样的。
需要提醒的是,第一次调用时,请使用next()
语句或是send(None)
,不能使用send
发送一个非None
的值,否则会出错的,因为没有Python yield
语句来接收这个值。
下面来着重说明下send
执行的顺序。当第一次send(None)
(对应11行)时,启动生成器,从生成器函数的第一行代码开始执行,直到第一次执行完yield
(对应第4行)后,跳出生成器函数。这个过程中,n1
一直没有定义。
下面运行到send(1)
时,进入生成器函数,注意这里与调用next
的不同。这里是从第4行开始执行,把1
赋值给n1
,但是并不执行yield
部分。下面继续从yield
的下一语句继续执行,然后重新运行到yield
语句,执行后,跳出生成器函数。
即send
和next
相比,只是开始多了一次赋值的动作,其他运行流程是相同的。
def consumer():
r = 'here'
while True:
n1 = yield r
if not n1:
return
print('[CONSUMER] Consuming %s...' % n1)
r = '200 OK'+str(n1)
def produce(c):
aa = c.send(None)
n = 0
while n < 5:
n = n + 1
print('[PRODUCER] Producing %s...' % n)
r1 = c.send(n)
print('[PRODUCER] Consumer return: %s' % r1)
c.close()
c = consumer()
produce(c)
运行结果:
[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[PRODUCER] Consumer return: 200 OK1
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[PRODUCER] Consumer return: 200 OK2
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[PRODUCER] Consumer return: 200 OK3
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[PRODUCER] Consumer return: 200 OK4
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[PRODUCER] Consumer return: 200 OK5