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出现_warn_unsafe_extraction问题的方法
Mar 24 Python
python3 pandas 读取MySQL数据和插入的实例
Apr 20 Python
解决pycharm安装后代码区不能编辑的问题
Oct 28 Python
pandas 转换成行列表进行读取与Nan处理的方法
Oct 30 Python
对python实现合并两个排序链表的方法详解
Jan 23 Python
python中import与from方法总结(推荐)
Mar 21 Python
Python 面向对象之类class和对象基本用法示例
Feb 02 Python
关于torch.optim的灵活使用详解(包括重写SGD,加上L1正则)
Feb 20 Python
关于tf.matmul() 和tf.multiply() 的区别说明
Jun 18 Python
python3 简单实现组合设计模式
Jul 02 Python
python 爬虫网页登陆的简单实现
Nov 30 Python
OpenCV实现常见的四种图像几何变换
Apr 01 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
论建造顺序的重要性
2020/03/04 星际争霸
转换中文日期的PHP程序
2006/10/09 PHP
PHP批量采集下载美女图片的实现代码
2013/06/03 PHP
WordPress中重置文章循环的rewind_posts()函数讲解
2016/01/11 PHP
编写PHP脚本清除WordPress头部冗余代码的方法讲解
2016/03/01 PHP
Mac系统完美安装PHP7详细教程
2017/06/06 PHP
thinkPHP框架动态配置用法实例分析
2018/06/14 PHP
Javascript实例教程(19) 使用HoTMetal(3)
2006/12/23 Javascript
javascript 获取网页参数系统
2008/07/19 Javascript
jquery的Tooltip插件 qtip使用详细说明
2010/09/08 Javascript
javascript动态添加、修改、删除对象的属性与方法详解
2014/01/27 Javascript
jQuery地图map悬停显示省市代码分享
2015/08/20 Javascript
Bootstrap Chart组件使用教程
2016/04/28 Javascript
JS去除重复并统计数量的实现方法
2016/12/15 Javascript
利用jquery去掉时光轴头尾部线条的方法实例
2017/06/16 jQuery
Node.JS 循环递归复制文件夹目录及其子文件夹下的所有文件
2017/09/18 Javascript
js实现轮播图的两种方式(构造函数、面向对象)
2017/09/30 Javascript
ES6学习笔记之map、set与数组、对象的对比
2018/03/01 Javascript
微信小程序通过保存图片分享到朋友圈功能
2018/05/24 Javascript
微信小程序实现滑动操作代码
2020/04/23 Javascript
微信小程序之导航滑块视图容器功能的实现代码(简单两步)
2020/06/19 Javascript
[58:46]OG vs NAVI 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
跟老齐学Python之list和str比较
2014/09/20 Python
python动态网页批量爬取
2016/02/14 Python
python最长回文串算法
2018/06/04 Python
对pyqt5中QTabWidget的相关操作详解
2019/06/21 Python
django-allauth入门学习和使用详解
2019/07/03 Python
详解用Python为直方图绘制拟合曲线的两种方法
2019/08/21 Python
OpenCV+Python3.5 简易手势识别的实现
2020/12/21 Python
python中scipy.stats产生随机数实例讲解
2021/02/19 Python
Sephora丝芙兰菲律宾官方网站:购买化妆品和护肤品
2017/04/05 全球购物
美国领先的医疗警报服务:Philips Lifeline
2018/03/12 全球购物
优质飞蝇钓和渔具:RiverBum
2020/05/10 全球购物
Linux的主要特性
2016/09/03 面试题
opencv实现图像几何变换
2021/03/24 Python
高并发下Redis如何保持数据一致性(避免读后写)
2022/03/18 Redis