详解Python中的迭代器和使用
对于一个列表,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中的迭代器和使用的更多相关文章
- 举例详解Python中的split()函数的使用方法
这篇文章主要介绍了举例详解Python中的split()函数的使用方法,split()函数的使用是Python学习当中的基础知识,通常用于将字符串切片并转换为列表,需要的朋友可以参考下 函数:sp ...
- 详解Python中re.sub--转载
[背景] Python中的正则表达式方面的功能,很强大. 其中就包括re.sub,实现正则的替换. 功能很强大,所以导致用法稍微有点复杂. 所以当遇到稍微复杂的用法时候,就容易犯错. 所以此处,总结一 ...
- 详解Python中内置的NotImplemented类型的用法
它是什么? ? 1 2 >>> type(NotImplemented) <type 'NotImplementedType'> NotImplemented 是Pyth ...
- 详解Python中的循环语句的用法
一.简介 Python的条件和循环语句,决定了程序的控制流程,体现结构的多样性.须重要理解,if.while.for以及与它们相搭配的 else. elif.break.continue和pass语句 ...
- 详解python中@的用法
python中@的用法 @是一个装饰器,针对函数,起调用传参的作用. 有修饰和被修饰的区别,‘@function'作为一个装饰器,用来修饰紧跟着的函数(可以是另一个装饰器,也可以是函数定义). 代码1 ...
- Python Deque 模块使用详解,python中yield的用法详解
Deque模块是Python标准库collections中的一项. 它提供了两端都可以操作的序列, 这意味着, 你可以在序列前后都执行添加或删除. https://blog.csdn.net/qq_3 ...
- 详解python三大器——迭代器、生成器、装饰器
迭代器 聊迭代器前我们要先清楚迭代的概念:通常来讲从一个对象中依次取出数据,这个过程叫做遍历,这个手段称为迭代(重复执行某一段代码块,并将每一次迭代得到的结果作为下一次迭代的初始值). 可迭代对象(i ...
- 详解 Python 中的下划线命名规则
在 python 中,下划线命名规则往往令初学者相当 疑惑:单下划线.双下划线.双下划线还分前后……那它们的作用与使用场景 到底有何区别呢?今天 就来聊聊这个话题. 1.单下划线(_) 通常情况下,单 ...
- 详解Python中的__init__和__new__(静态方法)
一.__init__ 方法是什么? 使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候.例如: #-*- co ...
随机推荐
- kafka 分区数
Kafka的分区,相当于把一个Topic再细分成了多个通道(对应 多个线程) 部署的时候尽量做到一个消费者(线程)对应一个分区. 如何确定Kafka的分区数,key和consumer线程数,以及不消费 ...
- activiti-ui源码构建
修改数据库链接:
- 使用 mybatis和oracle 数据库出现的问题
mybatis 官网教程 http://www.mybatis.org/mybatis-3/zh/dynamic-sql.html 出现 Could not set parameters for ma ...
- Java中的new关键字和引用传参
先看看Java中如何使用new关键字创建一个对象的. [java] view plain copy public class Student { public String name; public ...
- mysql主从怎么样使主为innodb辅为myisam
MySQL主从复制(linux主+windows从) http://blog.csdn.net/qq_20032995/article/details/54380290 mysql主从怎么样使主为in ...
- HDU 1039.Easier Done Than Said?-条件判断字符串
Easier Done Than Said? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/O ...
- python aiohttp sancio 框架性能测试
开头先啰嗦两句: 由于本人有开发一个博客的打算,所以近期开始选型python的web框架重头学习,选了两款非常火的 aio web框架 aiohttp 和 sancio 进行性能测试以及开发喜好的调研 ...
- [NOI2018]屠龙勇士(exCRT)
首先很明显剑的选择是唯一的,直接用multiset即可. 接下来可以发现每条龙都是一个模线性方程.设攻击第i条龙的剑的攻击力为$s_i$,则$s_ix\equiv a_i\ (mod\ p_i)$. ...
- CodeForces - 981D Bookshelves
Discription Mr Keks is a typical white-collar in Byteland. He has a bookshelf in his office with som ...
- 洛谷 P2742 [USACO5.1]圈奶牛Fencing the Cows
题目描述 农夫约翰想要建造一个围栏用来围住他的奶牛,可是他资金匮乏.他建造的围栏必须包括他的奶牛喜欢吃草的所有地点.对于给出的这些地点的坐标,计算最短的能够围住这些点的围栏的长度. 输入输出格式 输入 ...