彻底理解Python中的yield关键字


Posted in Python onApril 01, 2019

阅读别人的python源码时碰到了这个yield这个关键字,各种搜索终于搞懂了,在此做一下总结:

  • 通常的for...in...循环中,in后面是一个数组,这个数组就是一个可迭代对象,类似的还有链表,字符串,文件。它可以是mylist = [1, 2, 3],也可以是mylist = [x*x for x in range(3)]。它的缺陷是所有数据都在内存中,如果有海量数据的话将会非常耗内存。
  • 生成器是可以迭代的,但只可以读取它一次。因为用的时候才生成。比如 mygenerator = (x*x for x in range(3)),注意这里用到了(),它就不是数组,而上面的例子是[]。
  • 我理解的生成器(generator)能够迭代的关键是它有一个next()方法,工作原理就是通过重复调用next()方法,直到捕获一个异常。可以用上面的mygenerator测试。
  • 带有 yield 的函数不再是一个普通函数,而是一个生成器generator,可用于迭代,工作原理同上。
  • yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的值。重点是:下一次迭代时,从上一次迭代遇到的yield后面的代码(下一行)开始执行。
  • 简要理解:yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始。
  • 带有yield的函数不仅仅只用于for循环中,而且可用于某个函数的参数,只要这个函数的参数允许迭代参数。比如array.extend函数,它的原型是array.extend(iterable)。
  • send(msg)与next()的区别在于send可以传递参数给yield表达式,这时传递的参数会作为yield表达式的值,而yield的参数是返回给调用者的值。——换句话说,就是send可以强行修改上一个yield表达式值。比如函数中有一个yield赋值,a = yield 5,第一次迭代到这里会返回5,a还没有赋值。第二次迭代时,使用.send(10),那么,就是强行修改yield 5表达式的值为10,本来是5的,那么a=10
  • send(msg)与next()都有返回值,它们的返回值是当前迭代遇到yield时,yield后面表达式的值,其实就是当前迭代中yield后面的参数。
  • 第一次调用时必须先next()或send(None),否则会报错,send后之所以为None是因为这时候没有上一个yield(根据第8条)。可以认为,next()等同于send(None)。

代码示例1:

#encoding:UTF-8 
def yield_test(n): 
  for i in range(n): 
    yield call(i) 
    print("i=",i) 
  #做一些其它的事情   
  print("do something.")   
  print("end.") 
def call(i): 
  return i*2 
#使用for循环 
for i in yield_test(5): 
  print(i,",")

结果是:

>>>  
0 , 
i= 0 
2 , 
i= 1 
4 , 
i= 2 
6 , 
i= 3 
8 , 
i= 4 
do something. 
end. 
>>>

理解的关键在于:下次迭代时,代码从yield的下一跳语句开始执行。

代码示例2:

def node._get_child_candidates(self, distance, min_dist, max_dist):
  if self._leftchild and distance - max_dist < self._median:
    yield self._leftchild
  if self._rightchild and distance + max_dist >= self._median:
    yield self._rightchild

与前面不同的是,这个函数中没有for循环,但它依然可以用于迭代。

node._get_child_candidates函数中有yield,所以它变成了一个迭代器,可以用于迭代。

执行第一次迭代时(其实就是调用next()方法),如果有左节点并且距离满足要求,会执行第一个yield,这时会返回self._leftchild并完成第一个迭代。

执行第二次迭代时,从第一个yield后面开始,如果有右节点并且距离满足要求,会执行第二个yield,这时会返回self._rightchild并完成第一个迭代。

执行第三次迭代时,第二个yield后再无代码,捕获异常,退出迭代。

调用过程:

result, candidates = list(), [self]
while candidates:
  node = candidates.pop()
  distance = node._get_dist(obj)
  if distance <= max_dist and distance >= min_dist:
    result.extend(node._values)
  candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
return result

上面的node._get_child_candidates(self, distance, min_dist, max_dist)是放在extend()函数中作为参数的,为什么可以这么用,就因为extend函数的参数不仅仅支持array,只要它是一个迭代器就可以。它的原型是array.extend(iterable)。

代码示例3:

彻底理解Python中的yield关键字

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。如果你想了解更多相关内容请查看下面相关链接

Python 相关文章推荐
python Django连接MySQL数据库做增删改查
Nov 07 Python
Python制作爬虫抓取美女图
Jan 20 Python
关于Python面向对象编程的知识点总结
Feb 14 Python
详解python 字符串和日期之间转换 StringAndDate
May 04 Python
python正则中最短匹配实现代码
Jan 16 Python
单链表反转python实现代码示例
Feb 08 Python
Python字符串逆序的实现方法【一题多解】
Feb 18 Python
python 怎样将dataframe中的字符串日期转化为日期的方法
Sep 26 Python
Python3监控windows,linux系统的CPU、硬盘、内存使用率和各个端口的开启情况详细代码实例
Mar 18 Python
Django使用rest_framework写出API
May 21 Python
Python排序算法之插入排序及其优化方案详解
Jun 11 Python
Python matplotlib绘制条形统计图 处理多个实验多组观测值
Apr 21 Python
python抓取搜狗微信公众号文章
Apr 01 #Python
Python使用os.listdir()和os.walk()获取文件路径与文件下所有目录的方法
Apr 01 #Python
python装饰器简介---这一篇也许就够了(推荐)
Apr 01 #Python
Python批量删除只保留最近几天table的代码实例
Apr 01 #Python
Python中的Socket 与 ScoketServer 通信及遇到问题解决方法
Apr 01 #Python
python assert的用处示例详解
Apr 01 #Python
使用Python操作FTP实现上传和下载的方法
Apr 01 #Python
You might like
php5.3 注意事项说明
2013/07/01 PHP
php生成随机颜色方法汇总
2014/12/03 PHP
php curl请求信息和返回信息设置代码实例
2015/04/27 PHP
PHP读取大文件的多种方法介绍
2016/04/04 PHP
thinkphp表单上传文件并将文件路径保存到数据库中
2016/07/28 PHP
PHP面向对象程序设计之对象克隆clone和魔术方法__clone()用法分析
2019/06/12 PHP
redis+php实现微博(二)发布与关注功能详解
2019/09/23 PHP
js脚本学习 比较实用的基础
2006/09/07 Javascript
js+CSS 图片等比缩小并垂直居中实现代码
2008/12/01 Javascript
poshytip 基于jquery的 插件 主要用于显示微博人的图像和鼠标提示等
2012/10/12 Javascript
javascript数组去重3种方法的性能测试与比较
2013/03/26 Javascript
JavaScript修改浏览器tab标题小技巧
2015/01/06 Javascript
解决js图片加载时出现404的问题
2020/11/30 Javascript
JS如何设置iOS中微信浏览器的title
2016/11/22 Javascript
详解Js模板引擎(TrimPath)
2016/11/22 Javascript
详解利用Angular实现多团队模块化SPA开发框架
2017/11/27 Javascript
NUXT SSR初级入门笔记(小结)
2019/12/16 Javascript
详解如何利用Cython为Python代码加速
2018/01/27 Python
python贪婪匹配以及多行匹配的实例讲解
2018/04/19 Python
为什么Python中没有&quot;a++&quot;这种写法
2018/11/27 Python
jupyter notebook 参数传递给shell命令行实例
2020/04/10 Python
Django ORM 查询表中某列字段值的方法
2020/04/30 Python
Pycharm打开已有项目配置python环境的方法
2020/07/03 Python
Django怎么在admin后台注册数据库表
2020/11/14 Python
HTML5离线应用与客户端存储的实现
2018/05/03 HTML / CSS
苹果美国官方商城:Apple美国
2016/08/24 全球购物
OPPO手机官方商城:中国手机市场出货量第一品牌
2017/10/18 全球购物
美国高级音响品牌:Master&Dynamic
2018/07/05 全球购物
通往英国高街的商店橱窗:Down Your High Street
2020/07/19 全球购物
若通过ObjectOutputStream向一个文件中多次以追加方式写入object,为什么用ObjectInputStream读取这些object时会产生StreamCorruptedException?
2016/10/17 面试题
采购主管工作职责
2013/12/12 职场文书
《奇妙的国际互联网》 教学反思
2014/02/25 职场文书
乡镇党建工作汇报材料
2014/08/14 职场文书
党的群众路线教育实践活动督导组工作情况汇报
2014/10/28 职场文书
合同权益转让协议书模板
2014/11/18 职场文书
公司员工奖惩制度
2015/08/04 职场文书