浅谈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命令行参数解析模块getopt使用实例
Apr 13 Python
Python基础知识_浅谈用户交互
May 31 Python
urllib和BeautifulSoup爬取维基百科的词条简单实例
Jan 17 Python
ubuntu安装mysql pycharm sublime
Feb 20 Python
几种实用的pythonic语法实例代码
Feb 24 Python
Python实现基于TCP UDP协议的IPv4 IPv6模式客户端和服务端功能示例
Mar 22 Python
python绘制简单彩虹图
Nov 19 Python
PyQt5固定窗口大小的方法
Jun 18 Python
django 模版关闭转义方式
May 14 Python
keras 指定程序在某块卡上训练实例
Jun 22 Python
在Django中使用MQTT的方法
May 10 Python
Pytorch反向传播中的细节-计算梯度时的默认累加操作
Jun 05 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遍历某个目录下的所有文件和子文件夹的实现代码
2013/06/28 PHP
制作安全性高的PHP网站的几个实用要点
2014/12/30 PHP
php5.4以下版本json不支持不转义内容中文的解决方法
2015/01/13 PHP
php有效防止图片盗用、盗链的两种方法
2016/11/01 PHP
TP5多入口设置实例讲解
2020/12/15 PHP
从Ajax到JQuery Ajax学习
2007/02/14 Javascript
怎么清空javascript数组
2013/05/11 Javascript
JavaScript验证图片类型(扩展名)的函数分享
2014/05/05 Javascript
使用AngularJS创建自定义的过滤器的方法
2015/06/18 Javascript
Vue 进入/离开动画效果
2017/12/26 Javascript
webpack-dev-server远程访问配置方法
2018/02/22 Javascript
微信小程序实现折叠与展开文章功能
2018/06/12 Javascript
微信小程序中使用ECharts 异步加载数据的方法
2018/06/27 Javascript
详解SPA中前端路由基本原理与实现方式
2018/09/12 Javascript
Vue指令指令大全
2019/02/09 Javascript
JavaScript Tab菜单实现过程解析
2020/05/13 Javascript
Openlayers显示瓦片网格信息的方法
2020/09/28 Javascript
[42:22]DOTA2上海特级锦标赛C组小组赛#1 OG VS Archon第一局
2016/02/27 DOTA
Python的Django框架可适配的各种数据库介绍
2015/07/15 Python
在Python的Django框架中获取单个对象数据的简单方法
2015/07/17 Python
Python语言实现获取主机名根据端口杀死进程
2016/03/31 Python
Python连接DB2数据库
2016/08/27 Python
Python中应该使用%还是format来格式化字符串
2018/09/25 Python
Python中作用域的深入讲解
2018/12/10 Python
python图像和办公文档处理总结
2019/05/28 Python
python用类实现文章敏感词的过滤方法示例
2019/10/27 Python
解决Tensorboard可视化错误:不显示数据 No scalar data was found
2020/02/15 Python
Pandas时间序列:时期(period)及其算术运算详解
2020/02/25 Python
使用Matplotlib绘制不同颜色的带箭头的线实例
2020/04/17 Python
团员学习总结的自我评价范文
2013/10/14 职场文书
《故乡》教学反思
2014/04/10 职场文书
绿色家庭事迹材料
2014/05/01 职场文书
建筑工程质量通病防治方案
2014/06/08 职场文书
师德师风自我评价范文
2014/09/11 职场文书
大学生年度个人总结
2015/02/15 职场文书
使用Spring处理x-www-form-urlencoded方式
2021/11/02 Java/Android