Python迭代和迭代器详解


Posted in Python onNovember 10, 2016

迭代器

迭代器(iterator)有时又称游标(cursor)是程式设计的软件设计模式,可在容器物件(container,例如链表或阵列)上遍访的界面,设计人员无需关心容器物件的内存分配的实现细节。

摘自维基百科

也就是说迭代器类似于一个游标,卡到哪里就是哪里,可以通过这个来访问某个可迭代对象的元素;同时,也不是只有Python有这个特性。比如C++的STL中也有这个,如 vector<int>::iterator it 。下面主要说一下Python中的可迭代对象和迭代器吧。

Python可迭代对象(Iterable)

Python中经常使用 for 来对某个对象进行遍历,此时被遍历的这个对象就是可迭代对象,像常见的 list , tuple 都是。如果给一个准确的定义的话,就是只要它定义了可以返回一个迭代器的 __iter__ 方法,或者定义了可以支持下标索引的 __getitem__ 方法(这些双下划线方法会在其他章节中全面解释),那么它就是一个可迭代对象。

Python迭代器(iterator)

迭代器是通过 next() 来实现的,每调用一次他就会返回下一个元素,当没有下一个元素的时候返回一个 StopIteration 异常,所以实际上定义了这个方法的都算是迭代器。可以用通过下面例子来体验一下迭代器:

In [38]: s = 'ab'

In [39]: it = iter(s)

In [40]: it
Out[40]: <iterator at 0x1068e6d50>

In [41]: print it
<iterator object at 0x1068e6d50>

In [42]: it.next()
Out[42]: 'a'

In [43]: it.next()
Out[43]: 'b'

In [44]: it.next()
---------------------------------------------------------------------------
StopIteration               Traceback (most recent call last)
<ipython-input-44-54f0920595b2> in <module>()
----> 1 it.next()

StopIteration:

自己实现一个迭代器,如下(参见官网文档):

class Reverse:
  """Iterator for looping over a sequence backwards."""
  def __init__(self, data):
    self.data = data
    self.index = len(data)

  def __iter__(self):
    return self

  def next(self):
    if self.index == 0:
      raise StopIteration
    self.index = self.index - 1
    return self.data[self.index]

rev = Reverse('spam')
for char in rev:
  print char

[output]
m
a
p
s

生成器(Generators)

生成器是构造迭代器的最简单有力的工具,与普通函数不同的只有在返回一个值的时候使用 yield 来替代 return ,然后 yield 会自动构建好 next() 和 iter() 。是不是很省事。例如:

def reverse(data):
  for index in range(len(data)-1, -1, -1):
    yield data[index]

>>> for char in reverse('golf'):
...   print char
...
f
l
o
g

生成器最佳应用场景是:你不想同一时间将所有计算出来的大量结果集分配到内存当中,特别是结果集里还包含循环。比方说,循环打印1000000个数,我们一般会使用 xrange() 而不是 range() ,因为前者返回的是生成器,后者返回的是列表(列表消耗大量空间)。

Help on built-in function range in module __builtin__:

range(...)
  range(stop) -> list of integers
  range(start, stop[, step]) -> list of integers

  Return a list containing an arithmetic progression of integers.
  range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
  When step is given, it specifies the increment (or decrement).
  For example, range(4) returns [0, 1, 2, 3]. The end point is omitted!
  These are exactly the valid indices for a list of 4 elements.

class xrange(object)
 | xrange(stop) -> xrange object
 | xrange(start, stop[, step]) -> xrange object
 |
 | Like range(), but instead of returning a list, returns an object that
 | generates the numbers in the range on demand. For looping, this is
 | slightly faster than range() and more memory efficient.
iter()

将可迭代对象转化为迭代器。

In [113]: s = 'abc'

In [114]: s.next()
---------------------------------------------------------------------------
AttributeError              Traceback (most recent call last)
<ipython-input-114-5e5e6532ea26> in <module>()
----> 1 s.next()

AttributeError: 'str' object has no attribute 'next'

In [115]: it = iter(s)

In [116]: it.next()
Out[116]: 'a'

生成器表达式

和列表推导式唯一的区别就是中括号换成了小括号,如下:

In [119]: num = (i for i in range(10))

In [120]: sum(num)
Out[120]: 45
Python 相关文章推荐
浅谈编码,解码,乱码的问题
Dec 30 Python
运行django项目指定IP和端口的方法
May 14 Python
Django开发中的日志输出的方法
Jul 02 Python
Python实现批量执行同目录下的py文件方法
Jan 11 Python
Mac在python3环境下安装virtualwrapper遇到的问题及解决方法
Jul 09 Python
python pip安装包出现:Failed building wheel for xxx错误的解决
Dec 25 Python
Python基于requests库爬取网站信息
Mar 02 Python
Pycharm激活码激活两种快速方式(附最新激活码和插件)
Mar 12 Python
python如何快速生成时间戳
Jul 21 Python
详解Python 函数参数的拆解
Sep 02 Python
Python3利用scapy局域网实现自动多线程arp扫描功能
Jan 21 Python
一篇文章带你搞懂Python类的相关知识
May 20 Python
python通过cookie模拟已登录状态的初步研究
Nov 09 #Python
Python内置函数OCT详解
Nov 09 #Python
windows10系统中安装python3.x+scrapy教程
Nov 08 #Python
简单谈谈python中的多进程
Nov 06 #Python
python自带的http模块详解
Nov 06 #Python
Python程序中设置HTTP代理
Nov 06 #Python
Python 搭建Web站点之Web服务器网关接口
Nov 06 #Python
You might like
PHP用户指南-cookies部分
2006/10/09 PHP
thinkPHP查询方式小结
2016/01/09 PHP
Symfony2在Nginx下的配置方法图文教程
2016/02/04 PHP
CI框架封装的常用图像处理方法(缩略图,水印,旋转,上传等)
2016/11/22 PHP
php微信公众平台示例代码分析(二)
2016/12/06 PHP
PHP回调函数概念与用法实例分析
2017/11/03 PHP
用Greasemonkey 脚本收藏网站会员信息到本地
2009/10/26 Javascript
js 多浏览器分别判断代码
2010/04/01 Javascript
Javascript中找到子元素在父元素内相对位置的代码
2012/07/21 Javascript
JavaScript高级程序设计 阅读笔记(十七) js事件
2012/08/14 Javascript
当jQuery1.7遇上focus方法的问题
2014/01/26 Javascript
jQuery+PHP实现可编辑表格字段内容并实时保存
2015/10/09 Javascript
javascript实现unicode与ASCII相互转换的方法
2015/12/10 Javascript
详解Javascript事件驱动编程
2016/01/03 Javascript
js实现自动图片轮播代码
2017/03/22 Javascript
基于jQuery的表单填充实例
2017/08/22 jQuery
jQuery选择器之属性过滤选择器详解
2017/09/28 jQuery
用Axios Element实现全局的请求loading的方法
2018/03/15 Javascript
JS实现电话号码的字母组合算法示例
2019/02/26 Javascript
深入理解令牌认证机制(token)
2019/08/22 Javascript
vue 解决form表单提交但不跳转页面的问题
2019/10/30 Javascript
python实现12306抢票及自动邮件发送提醒付款功能
2018/03/08 Python
python 通过可变参数计算n个数的乘积方法
2019/06/13 Python
python+jinja2实现接口数据批量生成工具
2019/08/28 Python
Django 限制访问频率的思路详解
2019/12/24 Python
Sarenza德国:法国最大的时尚鞋和包包网上商店
2019/06/08 全球购物
使用索引有什么好处
2016/07/27 面试题
How TDD works
2012/09/30 面试题
签约仪式主持词
2014/03/19 职场文书
开门红主持词
2014/04/02 职场文书
和谐社区口号
2014/06/19 职场文书
医生见习报告范文
2014/11/03 职场文书
自荐信格式模板
2015/03/27 职场文书
交通安全月活动总结
2015/05/08 职场文书
2016年学校“3.12”植树节活动总结
2016/03/16 职场文书
nginx之queue的具体使用
2022/06/28 Servers