对于一个列表,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. codeforces Round 442 B Nikita and string【前缀和+暴力枚举分界点/线性DP】

    B. Nikita and string time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  2. IntelliJ IDEA 常用设置/快捷键

    经常用到 IntelliJ IDEA 编写java,由于不时需要重装系统,所以Mark一下一些基本的设置选项,以便查询,这篇帖子会一直更新,只要有常用的新的设置或者快捷键 一.常用设置 显示代码行号 ...

  3. web.input()和web.data() 遇到特殊字符

    使用web.py的时候,web.input()和web.data() 都可以接收用户从浏览器端输入的参数. web.input()方法返回一个包含从url(GET方法)或http header(POS ...

  4. Codeforces Round #124 (Div. 1) C. Paint Tree(极角排序)

    C. Paint Tree time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  5. java应用高cpu占用

    一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环 排查故障如下: 1.根据top命令,发现PID为28555的Java进程占用CPU高达200%,出现故障 2.通过ps ...

  6. 微信小程序开发教程(八)视图层——.wxml详解

    框架的视图层由WXMKL(WeiXin Markup language)与WXSS(WeiXin Style Sheet)编写,由组件进行展示. 对于微信小程序而言,视图层就是所有.wxml文件与.w ...

  7. [Lydsy1805月赛] 对称数

    挺不错的一道数据结构题QWQ. 一开始发现这个题如果不看数据范围的话,妥妥的树上莫队啊23333,然鹅10组数据是不可能让你舒舒服服的树上莫队卡过的23333 于是想了想,这个题的模型就是,把u到v链 ...

  8. [USACO06DEC] Milk Patterns

    题目描述 Farmer John has noticed that the quality of milk given by his cows varies from day to day. On f ...

  9. 【DFS】URAL - 2104 - Game with a Strip

    大概就是dfs?当前区间(l,r)的答案可以由(l,m)和(m+1,r)区间推出,如果某个区间已经完全被某种颜色覆盖,那么就返回该颜色.否则按照递归层数判定,奇数层Alice占优势,只需左右区间中一者 ...

  10. jQuery 移除绑定事件

    移除事件 unbind(type [,data])     //data是要移除的函数 $('#btn').unbind("click"); //移除click $('#btn') ...