python中yield的用法详解——最简单,最清晰的解释


Posted in Python onApril 04, 2019

首先我要吐槽一下,看程序的过程中遇见了yield这个关键字,然后百度的时候,发现没有一个能简单的让我懂的,讲起来真TM的都是头头是道,什么参数,什么传递的,还口口声声说自己的教程是最简单的,最浅显易懂的,我就想问没有有考虑过读者的感受。

接下来是正题:

首先,如果你还没有对yield有个初步分认识,那么你先把yield看做“return”,这个是直观的,它首先是个return,普通的return是什么意思,就是在程序中返回某个值,返回之后程序就不再往下运行了。看做return之后再把它看做一个是生成器(generator)的一部分(带yield的函数才是真正的迭代器),好了,如果你对这些不明白的话,那先把yield看做return,然后直接看下面的程序,你就会明白yield的全部意思了:

def foo():
 print("starting...")
 while True:
  res = yield 4
  print("res:",res)
g = foo()
print(next(g))
print("*"*20)
print(next(g))

就这么简单的几行代码就让你明白什么是yield,代码的输出这个:

starting...
4
********************
res: None
4

我直接解释代码运行顺序,相当于代码单步调试:

1.程序开始执行以后,因为foo函数中有yield关键字,所以foo函数并不会真的执行,而是先得到一个生成器g(相当于一个对象)

2.直到调用next方法,foo函数正式开始执行,先执行foo函数中的print方法,然后进入while循环

3.程序遇到yield关键字,然后把yield想想成return,return了一个4之后,程序停止,并没有执行赋值给res操作,此时next(g)语句执行完成,所以输出的前两行(第一个是while上面的print的结果,第二个是return出的结果)是执行print(next(g))的结果,

4.程序执行print("*"*20),输出20个*

5.又开始执行下面的print(next(g)),这个时候和上面那个差不多,不过不同的是,这个时候是从刚才那个next程序停止的地方开始执行的,也就是要执行res的赋值操作,这时候要注意,这个时候赋值操作的右边是没有值的(因为刚才那个是return出去了,并没有给赋值操作的左边传参数),所以这个时候res赋值是None,所以接着下面的输出就是res:None,

6.程序会继续在while里执行,又一次碰到yield,这个时候同样return 出4,然后程序停止,print函数输出的4就是这次return出的4.

到这里你可能就明白yield和return的关系和区别了,带yield的函数是一个生成器,而不是一个函数了,这个生成器有一个函数就是next函数,next就相当于“下一步”生成哪个数,这一次的next开始的地方是接着上一次的next停止的地方执行的,所以调用next的时候,生成器并不会从foo函数的开始执行,只是接着上一步停止的地方开始,然后遇到yield后,return出要生成的数,此步就结束。

def foo():
 print("starting...")
 while True:
  res = yield 4
  print("res:",res)
g = foo()
print(next(g))
print("*"*20)
print(g.send(7))

再看一个这个生成器的send函数的例子,这个例子就把上面那个例子的最后一行换掉了,输出结果:

starting...
4
********************
res: 7
4

先大致说一下send函数的概念:此时你应该注意到上面那个的紫色的字,还有上面那个res的值为什么是None,这个变成了7,到底为什么,这是因为,send是发送一个参数给res的,因为上面讲到,return的时候,并没有把4赋值给res,下次执行的时候只好继续执行赋值操作,只好赋值为None了,而如果用send的话,开始执行的时候,先接着上一次(return 4之后)执行,先把7赋值给了res,然后执行next的作用,遇见下一回的yield,return出结果后结束。

5.程序执行g.send(7),程序会从yield关键字那一行继续向下运行,send会把7这个值赋值给res变量

6.由于send方法中包含next()方法,所以程序会继续向下运行执行print方法,然后再次进入while循环

7.程序执行再次遇到yield关键字,yield会返回后面的值后,程序再次暂停,直到再次调用next方法或send方法。

这就结束了,说一下,为什么用这个生成器,是因为如果用List的话,会占用更大的空间,比如说取0,1,2,3,4,5,6............1000

你可能会这样:

for n in range(1000):
 a=n

这个时候range(1000)就默认生成一个含有1000个数的list了,所以很占内存。

这个时候你可以用刚才的yield组合成生成器进行实现,也可以用xrange(1000)这个生成器实现

yield组合:

def foo(num):
 print("starting...")
 while num<10:
  num=num+1
  yield num
for n in foo(0):
 print(n)

输出:

starting...
1
2
3
4
5
6
7
8
9
10

xrange(1000):

for n in xrange(1000):
 a=n

其中要注意的是python3时已经没有xrange()了,在python3中,range()就是xrange()了,你可以在python3中查看range()的类型,它已经是个<class 'range'>了,而不是一个list了,毕竟这个是需要优化的。 

以上所述是小编给大家介绍的python中yield的用法详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
Python 面向对象 成员的访问约束
Dec 23 Python
让python json encode datetime类型
Dec 28 Python
Python 异常处理实例详解
Mar 12 Python
零基础写python爬虫之抓取百度贴吧代码分享
Nov 06 Python
Python使用selenium实现网页用户名 密码 验证码自动登录功能
May 16 Python
解决tensorflow测试模型时NotFoundError错误的问题
Jul 26 Python
利用Pycharm断点调试Python程序的方法
Nov 29 Python
Python设计模式之命令模式原理与用法实例分析
Jan 11 Python
Python二元赋值实用技巧解析
Oct 25 Python
Python 解决OPEN读文件报错 ,路径以及r的问题
Dec 19 Python
Python 字典一个键对应多个值的方法
Sep 29 Python
pandas按条件筛选数据的实现
Feb 20 Python
详解python项目实战:模拟登陆CSDN
Apr 04 #Python
Python实现字符串匹配的KMP算法
Apr 04 #Python
Python GUI编程完整示例
Apr 04 #Python
Python使用sax模块解析XML文件示例
Apr 04 #Python
详解小白之KMP算法及python实现
Apr 04 #Python
Python魔法方法功能与用法简介
Apr 04 #Python
详解pandas.DataFrame中删除包涵特定字符串所在的行
Apr 04 #Python
You might like
第十三节--对象串行化
2006/11/16 PHP
php+jquery编码方面的一些心得(utf-8 gb2312)
2010/10/12 PHP
PHP 前加at符合@的作用解析
2015/07/31 PHP
thinkPHP5.0框架独立配置与动态配置方法
2017/03/17 PHP
Laravel框架路由设置与使用示例
2018/06/12 PHP
编写针对IE的JS代码两种编写方法
2013/01/30 Javascript
网页前端优化之滚动延时加载图片示例
2013/07/13 Javascript
js日期对象兼容性的处理方法
2014/01/28 Javascript
jqeury-easyui-layout问题解决方法
2014/03/24 Javascript
js实现鼠标感应图片展示的方法
2015/02/27 Javascript
AngularJS基础学习笔记之控制器
2015/05/10 Javascript
jquery ztree异步搜索(搜叶子)实践
2016/02/25 Javascript
jQuery ajax请求返回list数据动态生成input标签,并把list数据赋值到input标签
2016/03/29 Javascript
使用微信内嵌H5网页解决JS倒计时失效问题
2017/01/13 Javascript
Vue.js实战之通过监听滚动事件实现动态锚点
2017/04/04 Javascript
bootstrap基本配置_动力节点Java学院整理
2017/07/14 Javascript
JS实现的将html转为pdf功能【基于浏览器端插件jsPDF】
2018/02/06 Javascript
JavaScript前端页面搜索功能案例【基于jQuery】
2019/07/10 jQuery
layui当点击文本框时弹出选择框,显示选择内容的例子
2019/09/02 Javascript
微信小程序如何播放腾讯视频的实现
2019/09/20 Javascript
初学vue出现空格警告的原因及其解决方案
2019/10/31 Javascript
echarts浮动显示单位的实现方法示例
2020/12/04 Javascript
python类和函数中使用静态变量的方法
2015/05/09 Python
Python学习入门之区块链详解
2017/07/25 Python
Python基于sklearn库的分类算法简单应用示例
2018/07/09 Python
Flask框架Flask-Principal基本用法实例分析
2018/07/23 Python
在Python文件中指定Python解释器的方法
2019/02/18 Python
flask框架渲染Jinja模板与传入模板变量操作详解
2020/01/25 Python
python+selenium+PhantomJS抓取网页动态加载内容
2020/02/25 Python
HTML5触摸事件实现移动端简易进度条的实现方法
2018/05/04 HTML / CSS
详解HTML5布局和HTML5标签
2020/10/26 HTML / CSS
世界上最大的网络主机公司:1&1
2016/10/12 全球购物
Cotton On美国网站:澳洲时装连锁品牌
2016/10/25 全球购物
NIHAOMARKET官方海外旗舰店:意大利你好华人超市
2018/01/27 全球购物
三年级音乐教学反思
2014/01/28 职场文书
领导班子三严三实心得体会
2014/10/13 职场文书