对于一个列表,a = [1, 2, 3, 4],我们最常见的遍历方式就是:

a = [1, 2, 3, 4]
for item in a:
print item

这里我们研究一种新的方式,就是迭代器。

在C++的STL中大量使用了迭代器,迭代器的作用当然就是遍历容器中的元素,而且他的好处就在于分离了容器的实现和遍历操作,不管我们使用什么类型的容器,使用迭代器的操作几乎是如出一辙。

 

看下面的代码:

>>> a = [2, 3, 4]
>>> it = iter(a)
>>> print it.next()
2
>>> print it.next()
3
>>> print it.next()
4
>>> print it.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>

在上面的代码中,iter函数创建了一个可以迭代的对象,然后每次调用next方法,都能从其中取出元素。当没有元素可以迭代时,便抛出一个异常StopIteration。

 

所以我们上面的for循环可以这样改写:

a = [1, 2, 3, 4]

it = iter(a)
item = None
while True:
try:
item = it.next()
except StopIteration:
break
print item #do_something

 

如何创建迭代器

 

现在我们想对我们自定义的class进行迭代操作,应该怎么办?

这里的关键是实现__iter__和next两个函数。

#!/usr/bin/env python
#coding: utf-8 class IterList:
def __init__(self, elem):
self.iter = iter(elem)
def __iter__(self):
return self
def next(self):
return self.iter.next() if __name__ == '__main__':
a = [1, 2, 3, 4]
test = IterList(a)
for item in test:
print item

这里我们仅仅是对class内部持有的元素做了一个包装,我们的__iter__返回的是自身,next则是调用的存储的iter的next方法。

 

现在我们提供一个稍微复杂的版本,这个版本可以允许向next函数传递参数,指定取出几个值。

#!/usr/bin/env python
#coding: utf-8 class IterList:
def __init__(self, elem):
self.iter = iter(elem)
def __iter__(self):
return self
def next(self, howmany=1):
result = []
for i in range(howmany):
try:
result.append(self.iter.next())
except StopIteration:
raise
return result if __name__ == '__main__':
s = range(20)
test = IterList(s)
print test.next()
print test.next()
print test.next(3)

这个例子能够让我们更加清晰的认识到next函数的工作原理。

 

用迭代器实现斐波那契数列

 

我们再给出最后一个关于斐波那契数列的例子:

对于斐波那契数列,我们可以这样实现:

def fab(max):
n, a, b = 0, 0, 1
L = []
while n < max:
L.append(b)
a, b = b, a + b
n = n + 1
return L if __name__ == '__main__':
for i in fab(5):
print i

上面的fab函数返回一个列表,记录斐波那契数列的值。

但是,当max过大的时候,fab就必须生成一个巨大的列表,这不仅占用大量内存,也会消耗过多的时间。

下面我们使用迭代器,给出一个更加高效的实现:

class Fab(object): 

    def __init__(self, max):
self.max = max
self.n, self.a, self.b = 0, 0, 1 def __iter__(self):
return self def next(self):
if self.n < self.max:
r = self.b
self.a, self.b = self.b, self.a + self.b
self.n = self.n + 1
return r
raise StopIteration() if __name__ == '__main__':
for i in Fab(5):
print i

这个版本高效在何处?

之前的版本是预先把一个巨大的结果生成,然后逐个去遍历,而这里调用Fab时,仅仅做了一个简单的初始化工作,真正的计算则是发生在每次迭代调用next的时候。所以这里不会占用过大的内存,而且不需要预先计算,也节约了时间。

 

本文最后部分参考了:http://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/

详解Python中的迭代器和使用的更多相关文章

  1. 举例详解Python中的split()函数的使用方法

    这篇文章主要介绍了举例详解Python中的split()函数的使用方法,split()函数的使用是Python学习当中的基础知识,通常用于将字符串切片并转换为列表,需要的朋友可以参考下   函数:sp ...

  2. 详解Python中re.sub--转载

    [背景] Python中的正则表达式方面的功能,很强大. 其中就包括re.sub,实现正则的替换. 功能很强大,所以导致用法稍微有点复杂. 所以当遇到稍微复杂的用法时候,就容易犯错. 所以此处,总结一 ...

  3. 详解Python中内置的NotImplemented类型的用法

    它是什么? ? 1 2 >>> type(NotImplemented) <type 'NotImplementedType'> NotImplemented 是Pyth ...

  4. 详解Python中的循环语句的用法

    一.简介 Python的条件和循环语句,决定了程序的控制流程,体现结构的多样性.须重要理解,if.while.for以及与它们相搭配的 else. elif.break.continue和pass语句 ...

  5. 详解python中@的用法

    python中@的用法 @是一个装饰器,针对函数,起调用传参的作用. 有修饰和被修饰的区别,‘@function'作为一个装饰器,用来修饰紧跟着的函数(可以是另一个装饰器,也可以是函数定义). 代码1 ...

  6. Python Deque 模块使用详解,python中yield的用法详解

    Deque模块是Python标准库collections中的一项. 它提供了两端都可以操作的序列, 这意味着, 你可以在序列前后都执行添加或删除. https://blog.csdn.net/qq_3 ...

  7. 详解python三大器——迭代器、生成器、装饰器

    迭代器 聊迭代器前我们要先清楚迭代的概念:通常来讲从一个对象中依次取出数据,这个过程叫做遍历,这个手段称为迭代(重复执行某一段代码块,并将每一次迭代得到的结果作为下一次迭代的初始值). 可迭代对象(i ...

  8. 详解 Python 中的下划线命名规则

    在 python 中,下划线命名规则往往令初学者相当 疑惑:单下划线.双下划线.双下划线还分前后……那它们的作用与使用场景 到底有何区别呢?今天 就来聊聊这个话题. 1.单下划线(_) 通常情况下,单 ...

  9. 详解Python中的__init__和__new__(静态方法)

    一.__init__ 方法是什么? 使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候.例如: #-*- co ...

随机推荐

  1. 无界面运行Jmeter压测脚本

    今天在针对单一接口压测时出现了从未遇到的问题,设好并发量后用调度器控制脚本的开始和结束,但在脚本应该自动结束时间,脚本却停不下来,手动stop报告就会有error率,卡了我很久很久不能解决,网络上也基 ...

  2. node中通过orm2链接mysql的一个坑

    代码是orm上的例子,出现如下错误: ORMError: Connection protocol not supported - have you installed the database dri ...

  3. 解决nextjs部署到now上之后出现的“Unable to import module 'now__launcher'”错误

    解决nextjs部署到now上之后出现的“Unable to import module 'now__launcher'”错误 这个错误是由于在next.config.js中直接引用了withLess ...

  4. scrapy详细数据流走向(个人总结)

    直接从数据流的角度来说比较容易理解: ·1.Spider创建一个初识url请求,把这个请求通过Engine转给Scheduler调度模块.然后Scheduler向Engine提供一个请求(这个请求是一 ...

  5. amq笔记:记一个关于PooledConnectionFactory的问题

    替人排查一个关于amq连接数的问题,使用PooledConnectionFactory进行连接池管理,设置了连接数上限为3,但部署到服务器之后,瞬间建立了几百个连接,用netstat -an 查看,发 ...

  6. ( 转 ) 优化 Group By -- MYSQL一次千万级连表查询优化

    概述: 交代一下背景,这算是一次项目经验吧,属于公司一个已上线平台的功能,这算是离职人员挖下的坑,随着数据越来越多,原本的SQL查询变得越来越慢,用户体验特别差,因此SQL优化任务交到了我手上. 这个 ...

  7. Hadoop下大矩阵乘法Version2

    1)使用本方法计算F*B,其中F是1000*1000的矩阵,B是1000*20000的矩阵,使用三个节点的集群,每个节点一个CPU核(集群装在虚拟机里,宿主机只有4个CPU核),每个节点配置一个map ...

  8. Word调整表格大小

    在Word文档中创建表格后,用户往往需要根据输入的内容调整表格的行高和列宽,有时也需要对整个表格的大小进行调整. 在选择的表格上右击,选择快捷菜单中的“自动调整”—“根据内容调整表格”命令,Word将 ...

  9. MySql优化--使用索引优化

    原文:http://blog.csdn.net/zuoanyinxiang/article/details/50606837 1.索引优化的原理   在没有使用索引的时候,数据库系统会根据要查找的值到 ...

  10. 利用LogParser分析IIS日志

    LogParser是微软官方出品的用于读取分析IIS日志的工具,使用类SQL语句过滤文本日志内容,并可将内容导出到csv.sqlserver作进一步分析    下载地址:http://www.micr ...