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 相关文章推荐
详解Python中内置的NotImplemented类型的用法
Mar 31 Python
Python实现简单的代理服务器
Jul 25 Python
python3.6连接MySQL和表的创建与删除实例代码
Dec 28 Python
python Pexpect 实现输密码 scp 拷贝的方法
Jan 03 Python
Python 移动光标位置的方法
Jan 20 Python
判断python对象是否可调用的三种方式及其区别详解
Jan 31 Python
使用Python和Scribus创建一个RGB立方体的方法
Jul 17 Python
python tkinter图形界面代码统计工具(更新)
Sep 18 Python
基于Python计算圆周率pi代码实例
Mar 25 Python
Python库skimage绘制二值图像代码实例
Apr 10 Python
Pytorch十九种损失函数的使用详解
Apr 29 Python
pandas按条件筛选数据的实现
Feb 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 foreach循环中使用引用的问题
2013/11/06 PHP
两个php日期控制类实例
2014/12/09 PHP
Laravel模板引擎Blade中section的一些标签的区别介绍
2015/02/10 PHP
WordPress开发中自定义菜单的相关PHP函数使用简介
2016/01/05 PHP
Yii核心验证器api详解
2016/11/23 PHP
异步加载script的代码
2011/01/12 Javascript
input输入框的自动匹配(原生代码)
2013/03/19 Javascript
jQuery窗口、文档、网页各种高度的精确理解
2014/07/02 Javascript
JavaScript中的方法调用详细介绍
2014/12/30 Javascript
javascript正则表达式中的replace方法详解
2015/04/20 Javascript
基于javascript实现图片懒加载
2016/01/05 Javascript
在线引用最新jquery文件的实现方法
2016/08/26 Javascript
Angular 常用指令实例总结整理
2016/12/13 Javascript
vue中更改数组中属性,在页面中不生效的解决方法
2019/10/30 Javascript
vue.js实现照片放大功能
2020/06/23 Javascript
[10:05]DOTA2-DPC中国联赛 正赛 iG vs PSG.LGD 选手采访
2021/03/11 DOTA
python对数组进行反转的方法
2015/05/20 Python
python读取文本绘制动态速度曲线
2018/06/21 Python
Python接口开发实现步骤详解
2020/04/26 Python
Python制作运行进度条的实现效果(代码运行不无聊)
2021/02/24 Python
使用Python快速打开一个百万行级别的超大Excel文件的方法
2021/03/02 Python
CSS3 @font-face属性使用指南
2014/12/12 HTML / CSS
美国最大的农村生活方式零售店:Tractor Supply Company(TSC)
2017/05/15 全球购物
纽约市的奢华内衣目的地:Anya Lust
2019/08/02 全球购物
英国豪华装饰照明品牌的在线零售商:Inspyer Lighting
2019/12/10 全球购物
药学专业毕业生求职信
2013/10/20 职场文书
党员自我批评与反省材料
2014/02/10 职场文书
培训主管的职业生涯规划
2014/03/06 职场文书
单位消防安全责任书
2014/07/23 职场文书
汽车修理厂管理制度
2015/08/05 职场文书
就业指导讲座心得体会
2016/01/15 职场文书
用Python写一个简易版弹球游戏
2021/04/13 Python
Java基础之this关键字的使用
2021/06/30 Java/Android
简单聊聊Golang中defer预计算参数
2022/03/25 Golang
Nginx隐藏式跳转(浏览器URL跳转后保持不变)
2022/04/07 Servers
MySQL数据库 安全管理
2022/05/06 MySQL