python中yield的用法详解


Posted in Python onJanuary 13, 2021

首先我要吐槽一下,看程序的过程中遇见了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中yield的用法内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Django中对数据查询结果进行排序的方法
Jul 17 Python
Python中列表和元组的相关语句和方法讲解
Aug 20 Python
Python爬虫实例扒取2345天气预报
Mar 04 Python
Python面向对象基础入门之编码细节与注意事项
Dec 11 Python
python批量下载抖音视频
Jun 17 Python
Python split() 函数拆分字符串将字符串转化为列的方法
Jul 16 Python
python 函数中的参数类型
Feb 11 Python
Python爬虫工具requests-html使用解析
Apr 29 Python
PyTorch的torch.cat用法
Jun 28 Python
python 装饰器的实际作用有哪些
Sep 07 Python
Python自动化测试基础必备知识点总结
Feb 07 Python
解决numpy和torch数据类型转化的问题
May 23 Python
利用python+request通过接口实现人员通行记录上传功能
Jan 13 #Python
selenium如何定位span元素的实现
Jan 13 #Python
python 进制转换 int、bin、oct、hex的原理
Jan 13 #Python
python pillow库的基础使用教程
Jan 13 #Python
用python-webdriver实现自动填表的示例代码
Jan 13 #Python
python 装饰器的基本使用
Jan 13 #Python
python日志通过不同的等级打印不同的颜色(示例代码)
Jan 13 #Python
You might like
给初学PHP的5个入手程序
2006/11/23 PHP
Linux下将excel数据导入到mssql数据库中的方法
2010/02/08 PHP
openPNE常用方法分享
2011/11/29 PHP
制作个性化的WordPress登陆界面的实例教程
2016/05/21 PHP
Yii2 RESTful中api的使用及开发实例详解
2016/07/06 PHP
jQuery 可以拖动的div实现代码 脚本之家修正版
2009/06/26 Javascript
JavaScript call apply使用 JavaScript对象的方法绑定到DOM事件后this指向问题
2011/09/28 Javascript
jQuery1.6 使用方法一
2011/11/23 Javascript
分享五个有用的jquery小技巧
2015/10/08 Javascript
基于jQuery实现简单的折叠菜单效果
2015/11/23 Javascript
深入理解JavaScript程序中内存泄漏
2016/03/17 Javascript
jquery使用Cookie和JSON记录用户最近浏览历史
2016/04/19 Javascript
javascript数字验证的实例代码(推荐)
2016/08/20 Javascript
node.js请求HTTPS报错:UNABLE_TO_VERIFY_LEAF_SIGNATURE\的解决方法
2016/12/18 Javascript
前端面试知识点锦集(JavaScript篇)
2016/12/28 Javascript
常用jQuery选择器汇总
2017/02/02 Javascript
canvas实现探照灯效果
2017/02/07 Javascript
微信小程序实现滴滴导航tab切换效果
2018/07/24 Javascript
jQuery实现根据身份证号获取生日、年龄、性别等信息的方法
2019/01/09 jQuery
JS数组Object.keys()方法的使用示例
2019/06/05 Javascript
layui 点击重置按钮, select 并没有被重置的解决方法
2019/09/03 Javascript
vue - vue.config.js中devServer配置方式
2019/10/30 Javascript
解决vuex数据页面刷新后初始化操作
2020/07/26 Javascript
jquery简易手风琴插件的封装
2020/10/13 jQuery
[01:20:47]DOTA2-DPC中国联赛 正赛 Ehome vs Magma BO3 第一场 1月19日
2021/03/11 DOTA
Python中getattr函数和hasattr函数作用详解
2016/06/14 Python
Python协程操作之gevent(yield阻塞,greenlet),协程实现多任务(有规律的交替协作执行)用法详解
2019/10/14 Python
如何基于pythonnet调用halcon脚本
2020/01/20 Python
python爬虫scrapy框架之增量式爬虫的示例代码
2021/02/26 Python
正宗的日本零食和糖果订阅盒:Bokksu
2019/11/21 全球购物
2014年药房工作总结
2014/11/22 职场文书
2015年环境整治工作总结
2015/05/22 职场文书
关于保护环境的建议书
2019/06/24 职场文书
适合青年人白手起家的创业项目分享
2019/08/16 职场文书
《童年》读后感(三篇)
2019/08/27 职场文书
Mysql中有关Datetime和Timestamp的使用总结
2021/12/06 MySQL