Python中的yield浅析


Posted in Python onJune 16, 2014

在介绍yield前有必要先说明下Python中的迭代器(iterator)和生成器(constructor)。

一、迭代器(iterator)

在Python中,for循环可以用于Python中的任何类型,包括列表、元祖等等,实际上,for循环可用于任何“可迭代对象”,这其实就是迭代器

迭代器是一个实现了迭代器协议的对象,Python中的迭代器协议就是有next方法的对象会前进到下一结果,而在一系列结果的末尾是,则会引发StopIteration。任何这类的对象在Python中都可以用for循环或其他遍历工具迭代,迭代工具内部会在每次迭代时调用next方法,并且捕捉StopIteration异常来确定何时离开。

使用迭代器一个显而易见的好处就是:每次只从对象中读取一条数据,不会造成内存的过大开销。

比如要逐行读取一个文件的内容,利用readlines()方法,我们可以这么写:

for line in open("test.txt").readlines():
    print line

这样虽然可以工作,但不是最好的方法。因为他实际上是把文件一次加载到内存中,然后逐行打印。当文件很大时,这个方法的内存开销就很大了。

利用file的迭代器,我们可以这样写:

for line in open("test.txt"):   #use file iterators
    print line

这是最简单也是运行速度最快的写法,他并没显式的读取文件,而是利用迭代器每次读取下一行。

二、生成器(constructor)

生成器函数在Python中与迭代器协议的概念联系在一起。简而言之,包含yield语句的函数会被特地编译成生成器。当函数被调用时,他们返回一个生成器对象,这个对象支持迭代器接口。函数也许会有个return语句,但它的作用是用来yield产生值的。

不像一般的函数会生成值后退出,生成器函数在生成值后会自动挂起并暂停他们的执行和状态,他的本地变量将保存状态信息,这些信息在函数恢复时将再度有效

>>> def g(n):
...     for i in range(n):
...             yield i **2
...
>>> for i in g(5):
...     print i,":",
...
0 : 1 : 4 : 9 : 16 :

要了解他的运行原理,我们来用next方法看看:
>>> t = g(5)
>>> t.next()
0
>>> t.next()
1
>>> t.next()
4
>>> t.next()
9
>>> t.next()
16
>>> t.next()
Traceback (most recent call last):
  File "", line 1, in 
StopIteration

在运行完5次next之后,生成器抛出了一个StopIteration异常,迭代终止。
再来看一个yield的例子,用生成器生成一个Fibonacci数列:

def fab(max):
    a,b = 0,1
    while a < max:
        yield a
        a, b = b, a+b
>>> for i in fab(20):
...     print i,",",
...
0 , 1 , 1 , 2 , 3 , 5 , 8 , 13 ,

看到这里应该就能理解生成器那个很抽象的概念了吧~~
Python 相关文章推荐
Python 两个列表的差集、并集和交集实现代码
Sep 21 Python
python字符串string的内置方法实例详解
May 14 Python
influx+grafana自定义python采集数据和一些坑的总结
Sep 17 Python
关于Django ForeignKey 反向查询中filter和_set的效率对比详解
Dec 15 Python
python的sorted用法详解
Jun 25 Python
win8.1安装Python 2.7版环境图文详解
Jul 01 Python
python使用for...else跳出双层嵌套循环的方法实例
May 17 Python
Pandas的Apply函数具体使用
Jul 21 Python
Python 数据的累加与统计的示例代码
Aug 03 Python
Python 代码调试技巧示例代码
Aug 11 Python
Django+Nginx+uWSGI 定时任务的实现方法
Jan 22 Python
python神经网络 使用Keras构建RNN训练
May 04 Python
python中使用enumerate函数遍历元素实例
Jun 16 #Python
Python中字典(dict)和列表(list)的排序方法实例
Jun 16 #Python
Python实现的几个常用排序算法实例
Jun 16 #Python
Python中文件遍历的两种方法
Jun 16 #Python
Python里隐藏的“禅”
Jun 16 #Python
Python程序设计入门(5)类的使用简介
Jun 16 #Python
Python程序设计入门(4)模块和包
Jun 16 #Python
You might like
摩卡咖啡
2021/03/03 咖啡文化
PHP封装的一个支持HTML、JS、PHP重定向的多功能跳转函数
2014/06/19 PHP
php创建和删除目录函数介绍和递归删除目录函数分享
2014/11/18 PHP
基于jquery的从一个页面跳转到另一个页面的指定位置的实现代码(带平滑移动的效果)
2011/05/24 Javascript
40款非常棒的jQuery 插件和制作教程(系列二)
2011/11/02 Javascript
JS 跳转页面延迟2种方法
2013/03/29 Javascript
使用AngularJS编写较为优美的JavaScript代码指南
2015/06/19 Javascript
JS数组操作(数组增加、删除、翻转、转字符串、取索引、截取(切片)slice、剪接splice、数组合并)
2016/05/20 Javascript
CentOS 安装NodeJS V8.0.0的方法
2017/06/15 NodeJs
基于js粘贴事件paste简单解析以及遇到的坑
2017/09/07 Javascript
使用vs code开发Nodejs程序的使用方法
2017/09/21 NodeJs
Angularjs渲染的 using 指令的星级评分系统示例
2017/11/09 Javascript
vue router-link传参以及参数的使用实例
2017/11/10 Javascript
Vue axios设置访问基础路径方法
2018/09/19 Javascript
简单说说如何使用vue-router插件的方法
2019/04/08 Javascript
VUE解决 v-html不能触发点击事件的问题
2019/10/28 Javascript
Vue实现渲染数据后控制滚动条位置(推荐)
2019/12/09 Javascript
[08:54]DOTA2-DPC中国联赛 正赛 Aster vs LBZS 选手采访
2021/03/11 DOTA
使用setup.py安装python包和卸载python包的方法
2013/11/27 Python
python使用ctypes模块调用windowsapi获取系统版本示例
2014/04/17 Python
用Python实现协同过滤的教程
2015/04/08 Python
Python视频爬虫实现下载头条视频功能示例
2018/05/07 Python
Python面向对象类继承和组合实例分析
2018/05/28 Python
Python实现的各种常见分布算法示例
2018/12/13 Python
Python BeautifulSoup [解决方法] TypeError: list indices must be integers or slices, not str
2019/08/07 Python
python生成器推导式用法简单示例
2019/10/08 Python
为什么是 Python -m
2020/06/19 Python
python调用win32接口进行截图的示例
2020/11/11 Python
澳大利亚领先的折扣药房:Chemist Direct(有中文站)
2018/11/24 全球购物
数控个人求职信范文
2014/02/03 职场文书
双方协议书
2014/04/22 职场文书
音乐幼师求职信
2014/07/09 职场文书
2019职场实习报告该怎么写?
2019/07/01 职场文书
珍惜时间的诗歌赏析
2019/08/23 职场文书
Python使用UDP实现720p视频传输的操作
2021/04/24 Python
JS开发前端团队展示控制器来为成员引流
2022/08/14 Javascript