使用异步IO时,generator是最基本的实现方式。 python生成器主要有两种方法,一种是send,一种是next。今天我们来看看两者的用法和联系。在每一段代码中,第一次next调用,相当于启动了生成器,会从生成器函数中的第一行代码开始执行,直到第一次执行yield语句(第4行),生成器函数会跳出来。然后第二次next调用,进入生成器函数后,从yield语句的下一条语句(第5行)开始执行,然后重新运行到yield语句。执行完后跳出生成器函数,再次调用next,以此类推。
这里我们以经典的生产者-消费者模型为例(来自廖雪峰的博客)
def consumer():
r = 0
for i in xrange(3):
yield r
r = '200 OK'+ str(i)
c = consumer()
n1 = c.next()
n2 = c.next()
n3 = c.next()
实际上,next() 和 send() 在某种意义上是相似的。不同的是send()可以传递yield表达式的值,而next()不能传递具体的值,只能传递None。因此,我们可以看到 c.next() 和 c.send(None) 具有相同的效果。
第一次调用时,请使用 next() 语句或 send(None)。不能使用 send 发送 None 以外的值,否则会出错,因为没有 Python 的 yield 语句来接收这个值。
下面描述发送执行的顺序。首先记住句子 n1 = yield r 是从右到左执行的。第一次send(None)时(对应第11行),启动生成器,从生成器函数的第一行代码开始执行,第一次执行yield后跳出生成器函数(对应行4) 。在这个过程中,n1 没有被定义。
当它运行到 send(1) 时,它进入生成器函数。此时,yield r 被视为一个整体,赋值给它并返回。此时相当于给n1赋值1,只是yield部分没有执行。接下来从yield的下一条语句继续执行,然后重新运行到yield语句。执行后,跳出生成器函数。即与next相比,send只开始多了一个赋值动作,其他运行的进程都一样。
def consumer():
r = 'here'
while True:
n1 = yield r #这里的等式右边相当于一个整体,接受回传值
if not n1:
return
print('[CONSUMER] Consuming %s...' % n1)
r = '%d00 OK' % 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: 100 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[PRODUCER] Consumer return: 300 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[PRODUCER] Consumer return: 400 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[PRODUCER] Consumer return: 500 OK
本文为原创文章,版权归知行编程网所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ python绘图中如何添加汉字的坐标轴09/09
- ♥ python strftime 获取当前时间01/14
- ♥ 使用 f 的 python 格式字符串08/30
- ♥ 大总结!Python进度条的那些事01/28
- ♥ 元组在 Python 中的使用12/14
- ♥ 如何在 spyder 中切换 Python 版本10/30
内容反馈