Python中的迭代器漫谈


Posted in Python onFebruary 03, 2015

问题是在Python中进行循环的时候产生的,熟悉Python的都知道,它没有类似其它语言中的for循环, 只能通过for in的方式进行循环遍历。最典型的应用就是通过range函数产生一个列表,然后用for in进行操作,如下:

#!/usr/bin/env python

for i in range(10):

    print i

代码的意义很好理解,range会产生一个列表,用for in最这个列表进行遍历,就有和类似for(i = 0;i<n;i++)同样的效果,range函数的详解可以看这里。问题又来了,range这个对象会产生一个列表,那么这个列表的内容铁定是存放在内存当中的,当需要的循环数量太大时,是相当占用内存的, 为了统计使用range占用内存的情况,我做了6次使用,分别用range产生100,10000,100000,1000000,10000000,100000000长度的列表,然后统计内存的占用:

测试代码 占用内存

range(100) 2.0MB

range(10000) 2.2MB

range(100000) 3.8MB

range(1000000) 19.5MB

range(10000000) 168.5MB

range(100000000) 1465.8MB

可以看到,随着基数的加大,占用内存呈几何倍数增加,显然在进行大循环操作的时候,要避免使用range。

为了解决上述问题,python提供了另外一个函数xrange,这个函数和range非常相似,但是占用内存比range会小很多,相关的说明可以查看这里,经过测试,用xrange产生的对象,不管参数是多少,占用内存几乎都没有变化。问题又来了,xrange内部是如何实现的,为什么和range性能相差这么大?为了验证我的猜想,先尝试用python实现类似xrange的函数zrange:

#!/usr/bin/env python

class zrange(object):

    def __init__(self,stop):

        self.__pointer=0

        self.stop=stop

    def __iter__(self):  

        return self  

    def next(self): #python3.0中,改用__next__

        if self.__pointer  >= self.stop:

            raise StopIteration

        else:

            self.__pointer = self.__pointer + 1

            return self.__pointer-1

test = zrange(10000000)

for i in test:

    print i

运行的结果和xrange一样, 对zrange进行内存占用测试,发现和xrange一样,参数的大小对内存占用几乎没有影响。那么它和range的区别在哪里呢?

前面说到,range产生的是一个列表,而无论是自定义的zrange还是系统内置的xrange产生的都是一个对象,像xrange或者zrange产生的对象,就叫做可迭代对象, 它给外部提供了一种遍历其内部元素,而不用关心其内部实现的方法。上面zrange的实现中, 最关键的实现是建立了一个内部指针__pointer, 它记录当前的访问的位置, 下次的访问就可以通过指针的状态进行相应的操作。

Python或者其它语言中,还有很多类似通过迭代的方式访问对象内容的,如读取一个文件中的内容:

#!/usr/bin/env python

f = open('zrange.py','r')

while True:

    line = f.readline()

    if not line:

        break

    print line.strip()

f.close()

大家都知道用readline要比reandlines节省资源,其实readline和readlines就类似于xrange和range,一个是通过指针记录当前位置,下次访问把指针往前移动一个单位,另外一个是直接把所有内容存放到内存当中。文件操作函数中,还可以通过seek手动的调整指针的位置,从而达到跳过或者重复读取某些内容的目的。

可以说,迭代器的实现中,其内部指针是节省资源,让迭代正常运行的关键。

Python 相关文章推荐
Python 代码性能优化技巧分享
Aug 07 Python
Python缩进和冒号详解
Jun 01 Python
Python下的Softmax回归函数的实现方法(推荐)
Jan 26 Python
Python实现的knn算法示例
Jun 14 Python
在Python中获取操作系统的进程信息
Aug 27 Python
tensorflow 获取checkpoint中的变量列表实例
Feb 11 Python
Python中pyecharts安装及安装失败的解决方法
Feb 18 Python
python实现门限回归方式
Feb 29 Python
Python爬虫设置ip代理过程解析
Jul 20 Python
Django项目创建及管理实现流程详解
Oct 13 Python
关于python类SortedList详解
Sep 04 Python
Python使用socket去实现TCP客户端和TCP服务端
Apr 12 Python
Python描述器descriptor详解
Feb 03 #Python
理解Python中的With语句
Feb 02 #Python
Linux环境下MySQL-python安装过程分享
Feb 02 #Python
Python中用pycurl监控http响应时间脚本分享
Feb 02 #Python
Python列表(list)常用操作方法小结
Feb 02 #Python
Python Sleep休眠函数使用简单实例
Feb 02 #Python
Python中实现从目录中过滤出指定文件类型的文件
Feb 02 #Python
You might like
php处理restful请求的路由类分享
2014/02/27 PHP
PHP foreach遍历多维数组实现方式
2016/11/16 PHP
5个javascript的数字格式化函数分享
2011/12/07 Javascript
javascript 判断中文字符长度的函数代码
2012/08/27 Javascript
jQuery 获取兄弟元素的几种不错方法
2014/05/23 Javascript
jQuery实现判断滚动条到底部
2015/06/23 Javascript
微信企业号开发之微信考勤Cookies的使用
2015/09/11 Javascript
使用基于Node.js的构建工具Grunt来发布ASP.NET MVC项目
2016/02/15 Javascript
学习使用AngularJS文件上传控件
2016/02/16 Javascript
Javascript之面向对象--方法
2016/12/02 Javascript
vue+vuex+axio从后台获取数据存入vuex实现组件之间共享数据
2017/04/22 Javascript
微信小程序tab切换可滑动切换导航栏跟随滚动实现代码
2019/09/04 Javascript
微信内置开发 iOS修改键盘换行为搜索的解决方案
2019/11/06 Javascript
详解JavaScript 高阶函数
2020/09/14 Javascript
JavaScript读取本地文件常用方法流程解析
2020/10/12 Javascript
nodejs使用Sequelize框架操作数据库的实现
2020/10/21 NodeJs
[03:54]DOTA2英雄梦之声_第06期_昆卡
2014/06/23 DOTA
[01:25:33]完美世界DOTA2联赛PWL S3 INK ICE vs Magma 第二场 12.20
2020/12/23 DOTA
Python实现从脚本里运行scrapy的方法
2015/04/07 Python
进一步探究Python中的正则表达式
2015/04/28 Python
python对url格式解析的方法
2015/05/13 Python
python实现播放音频和录音功能示例代码
2018/12/30 Python
python中的colorlog库使用详解
2019/07/05 Python
Pytorch .pth权重文件的使用解析
2020/02/14 Python
翻转数列python实现,求前n项和,并能输出整个数列的案例
2020/05/03 Python
python一些性能分析的技巧
2020/08/30 Python
pycharm 快速解决python代码冲突的问题
2021/01/15 Python
中东地区为妈妈们提供一切的头号购物目的地:Sprii
2018/05/06 全球购物
实习心得体会
2014/01/02 职场文书
个人近期表现材料
2014/02/11 职场文书
奥林匹克运动会口号
2014/06/19 职场文书
生物科学专业自荐书
2014/06/20 职场文书
大学生简短的自我评价
2014/09/12 职场文书
结婚当天新郎保证书
2015/05/08 职场文书
2015年幼儿教育工作总结
2015/07/24 职场文书
Java Optional<Foo>转换成List<Bar>的实例方法
2021/06/20 Java/Android