浅谈Python生成器generator之next和send的运行流程(详解)


Posted in Python onMay 08, 2017

对于普通的生成器,第一个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 相关文章推荐
python封装对象实现时间效果
Apr 23 Python
Python urllib模块urlopen()与urlretrieve()详解
Nov 01 Python
Python导出DBF文件到Excel的方法
Jul 25 Python
Python使用正则表达式抓取网页图片的方法示例
Apr 21 Python
python对DICOM图像的读取方法详解
Jul 17 Python
PySide和PyQt加载ui文件的两种方法
Feb 27 Python
python实现合并两个排序的链表
Mar 03 Python
对python3.4 字符串转16进制的实例详解
Jun 12 Python
opencv python 图像轮廓/检测轮廓/绘制轮廓的方法
Jul 03 Python
python的移位操作实现详解
Aug 21 Python
使用 django orm 写 exists 条件过滤实例
May 20 Python
详解Pycharm与anaconda安装配置指南
Aug 25 Python
python生成式的send()方法(详解)
May 08 #Python
python实时分析日志的一个小脚本分享
May 07 #Python
python分割列表(list)的方法示例
May 07 #Python
Python 常用的安装Module方式汇总
May 06 #Python
python中OrderedDict的使用方法详解
May 05 #Python
Python编程生成随机用户名及密码的方法示例
May 05 #Python
Python实现统计文本文件字数的方法
May 05 #Python
You might like
php之XML转数组函数的详解
2013/06/07 PHP
thinkphp中空模板与空模块的用法实例
2014/11/26 PHP
redirect_uri参数错误的解决方法(必看)
2017/02/16 PHP
javascript 事件绑定问题
2011/01/01 Javascript
得到jQuery detach()后节点中的某个值实现代码
2013/02/05 Javascript
深入理解javascript原型链和继承
2014/09/23 Javascript
JavaScript Date对象详解
2016/03/01 Javascript
在node中如何使用 ES6
2017/04/22 Javascript
在Vue组件化中利用axios处理ajax请求的使用方法
2017/08/25 Javascript
React Native基础入门之初步使用Flexbox布局
2018/07/02 Javascript
vue.js实现会动的简历(包含底部导航功能,编辑功能)
2019/04/08 Javascript
Vue源码学习之关于对Array的数据侦听实现
2019/04/23 Javascript
VSCode搭建Vue项目的方法
2020/04/30 Javascript
微信小程序实现电子签名功能
2020/07/29 Javascript
JS实现简单贪吃蛇小游戏
2020/10/28 Javascript
[07:54]DOTA2-DPC中国联赛 正赛 iG vs VG 选手采访
2021/03/11 DOTA
Python version 2.7 required, which was not found in the registry
2014/08/26 Python
Python实现的HTTP并发测试完整示例
2020/04/23 Python
python开发之函数定义实例分析
2015/11/12 Python
python调用Matplotlib绘制分布点并且添加标签
2018/05/31 Python
使用python将大量数据导出到Excel中的小技巧分享
2018/06/14 Python
彻彻底底地理解Python中的编码问题
2018/10/15 Python
Python3列表List入门知识附实例
2020/02/09 Python
详解python datetime模块
2020/08/17 Python
Python偏函数实现原理及应用
2020/11/20 Python
某公司的.net工程师面试题笔试题
2013/11/22 面试题
网络方面基础面试题
2012/11/16 面试题
高中毕业自我鉴定
2013/12/19 职场文书
失业者真诚求职信范文
2013/12/25 职场文书
红领巾心向党广播稿
2014/01/19 职场文书
企业内控岗位的职责
2014/02/07 职场文书
网络管理员岗位职责
2014/03/17 职场文书
退休教师欢送会主持词
2014/03/31 职场文书
财会专业毕业生自荐信
2014/07/09 职场文书
党员民主评议总结
2014/10/20 职场文书
政审证明材料
2015/06/19 职场文书