对于普通的生成器,第一个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
以上这篇浅谈Python生成器generator之next和send的运行流程(详解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持小牛知识库。
本文向大家介绍Python生成器(Generator)详解,包括了Python生成器(Generator)详解的使用技巧和注意事项,需要的朋友参考一下 通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 所以,如果列表元素可以
本文向大家介绍浅谈Python中列表生成式和生成器的区别,包括了浅谈Python中列表生成式和生成器的区别的使用技巧和注意事项,需要的朋友参考一下 列表生成式语法: 二者的区别很明显: 一个直接返回了表达式的结果列表, 而另一个是一个对象,该对象包含了对表达式结果的计算引用, 通过循环可以直接输出 结果 当表达式的结果数量较少的时候, 使用列表生成式还好, 一旦数量级过大, 那么列表生成式
本文向大家介绍python生成式的send()方法(详解),包括了python生成式的send()方法(详解)的使用技巧和注意事项,需要的朋友参考一下 随便在网上找了找,感觉都是讲半天讲不清楚,这里写一下。 输出: 为什么会这样呢,点进send就能看到一句话 send:Resumes the generator and "sends" a value that becomes the resul
本文向大家介绍老生常谈Python之装饰器、迭代器和生成器,包括了老生常谈Python之装饰器、迭代器和生成器的使用技巧和注意事项,需要的朋友参考一下 在学习python的时候,三大“名器”对没有其他语言编程经验的人来说,应该算是一个小难点,本次博客就博主自己对装饰器、迭代器和生成器理解进行解释。 为什么要使用装饰器 什么是装饰器?“装饰”从字面意思来谁就是对特定的建筑物内按照一定的思路和风格进行
问题内容: 基于生成器的协程具有一种方法,该方法允许调用方和被调用方之间进行双向通信,并从调用方恢复生成的生成协程。这是将生成器变成协程的功能。 尽管新的本机协程为异步I / O提供了出色的支持,但我看不出如何获得与之等效的协程。明确禁止使用in函数,因此本机协程只能使用一条语句返回一次。尽管表达式将新值带入协程中,但这些值来自被调用方,而不是调用方,并且等待的调用从每次开始就进行评估,而不是从中
generator 也就是生成器的英文拼写,它的主要作用是生成大批量的数据 方法一 (x for x in ['a', 'v']) 其实也就是把上一章迭代方法中的[]换成了(),那么返回的对象就不同了,前者是生成了一个list后者是生成了一个生成器。 其实跟js中的generator是一样的,打印出来这个生成器的内容只需要使用next()方法就OK了 l = ( x for x in ['1','