python中的迭代器和生成器(一)——迭代器
来源:互联网 发布:淘宝龙瞎多少钱 编辑:程序博客网 时间:2024/05/16 12:11
在学习python的资料中,经常看到迭代器和生成器,这样的名词。但到底什么是迭代器,什么是生成器?为什么会出现这样的类型,他们有什么便捷之处?
什么是迭代?
简单的讲就是循环操作,重复某一个过程很多次。可以用for循环对可迭代对象进行迭代。
什么是可迭代对象?
常见的迭代对象有序列,字典和文件等,另外还有其他的对象。这些可迭代对象的特点是:实现了__iter__方法。例如:
>>> alist=[1,2,3]>>> lst=alist.__iter__()>>> type(lst)<type 'listiterator'>>>> atuple=(1,2,3)>>> tup=atuple.__iter__()>>> type(tup)<type 'tupleiterator'>>>> afile=open(r"e:\test.txt",'r')>>> fl=afile.__iter__()>>> type(fl)<type 'file'>>>> astr='abc'>>> string=astr.__iter__()Traceback (most recent call last): File "<pyshell#62>", line 1, in <module> string=astr.__iter__()AttributeError: 'str' object has no attribute '__iter__'>>> iter(astr)<iterator object at 0x0212BE70>>>> string=iter(astr)>>> anum=1>>> iter(anum)Traceback (most recent call last): File "<pyshell#66>", line 1, in <module> iter(anum)TypeError: 'int' object is not iterable>>> type(string)<type 'iterator'>>>>
我们注意到,__iter__方法返回的对象就是迭代器对象。对于字符串astr来说,没有__iter__方法,但是可以用内建函数iter()来调用,所以是可迭代对象。而对于数字anum来说,iter()无法调用,所以是不可迭代的对象。因此可以用iter()来判断一个对象是否是可迭代对象。
内建函数iter()和方法__iter__的关系:
>>> help(list.__iter__)Help on wrapper_descriptor:__iter__(...) x.__iter__() <==> iter(x)>>>
什么是迭代器?
迭代器就是有一个 next() 方法的对象。
在Python3.0中迭代器规则有些变化,迭代器对象应该实现__next__方法,而不是next。而新的内建函数next可以用于访问这个方法。换句话说,next(it)等同于3.0之前版本中的it.next()。
看看上面的迭代器是否都有next():
>>> lst.next()1>>> tup.next()1>>> fl.next()'\xef\xbb\xbfHello world!\n'>>> string.next()'a'
如何迭代?
在后台,for 语句在容器对象中调用iter().该函数返回一个定义了next()方法的迭代器对象,它在容器中逐一访问元素。没有后续元素时,next()就会抛出一个 StopIteration 异常, 这并不表示错误发生, 只是通知外部调用者,for语句循环结束, 迭代完成。
以下是其工作原理的示例:
>>> s='abc'>>> it=iter(s)>>> it<iterator object at 0x0228F9D0>>>> it.next()'a'>>> it.next()'b'>>> it.next()'c'>>> it.next()Traceback (most recent call last): File "<pyshell#33>", line 1, in <module> it.next()StopIteration>>>
如何自定义迭代器?
了解了迭代器协议的后台机制,就可以很容易的给自己的类添加迭代器行为。定义一个 __iter__() 方法,使其返回一个带有 next() 方法的对象。如果这个类已经定义了 next(),那么 __iter__() 只需要返回self():
>>> class Reversestr:'Iterator for looping over a swquence backwards'def __init__(self,data):self.data = dataself.index = len(data)def __iter__(self):return selfdef next(self):if self.index == 0:raise StopIterationself.index = self.index - 1return self.data[self.index]>>> for char in Reversestr('spam'):print charmaps>>>
迭代器的优点是什么?列表不可以吗?
如果有一个可迭代计算值的函数,那么在使用时可能只需要获得指定的值,而不需要获得所有值的列表。这时候,如果数值很多,使用列表会占用太多的内存。当然,使用迭代器更简单更优雅。
看一个不使用列表的例子,因为那样列表的长度必须无限。
>>> class Fibs():def __init__(self):self.a=0self.b=1def next(self):self.a,self.b = self.b,self.a + self.breturn self.adef __iter__(self):return self>>>
构造一个Fibs对象:
>>> fibs = Fibs()在for循环中使用该对象——比如查找在斐波那契数列中比500大的最小的数:
>>> for f in fibs:if f > 500:print fbreak610因为设置了break,所以循环停止了,否则会一直继续下去。
迭代器和可迭代对象之间的关系
内建函数iter可以从可迭代对象中获取迭代器,以list为例:
>>> a=[1,2,3]>>> type(a)<type 'list'>>>> it=iter(a)>>> type(it)<type 'listiterator'>>>> it.next()1>>> it.next()2>>> it.next()3>>> it.next()Traceback (most recent call last): File "<pyshell#140>", line 1, in <module> it.next()StopIteration>>>
注:iter(a)和a.__iter__()等价。
反过来,使用list构造方法可以将迭代器转化为列表:
>>> a=[1,2,3]>>> it=iter(a)>>> list(it)[1, 2, 3]>>>
总结:
可迭代对象:一个实现了__iter__方法的对象。
迭代器:一个实现了next方法的对象。
关系:__iter__方法返回一个迭代器。
参考资料:
- Python参考手册
- Python基础教程(第2版)
- python中的迭代器和生成器(一)——迭代器
- python中的生成器和迭代器
- python中的迭代器和生成器
- Python中的迭代器和生成器
- python中的生成器和迭代器
- python中的生成器和迭代器
- python中的迭代器和生成器
- python中的迭代器和生成器
- python中的迭代器和生成器学习
- 深入讲解Python中的迭代器和生成器
- Python拾遗之迭代器和生成器(一)
- Python——迭代器和生成器
- python——迭代器和生成器
- Python中的迭代器iterator和yield生成器(constructor)
- python迭代器和生成器
- Python 迭代器和生成器
- Python 迭代器和生成器
- Python迭代器和生成器
- C#获取文件夹下的所有文件的文件名
- Spring mvc 项目中页面访问不到静态文件,如img , js , css 等
- 创业者们的十大迷思
- wince 隐藏任务栏
- 关于stuts2文件上传出错java.lang.NoSuchMethodException: com.cn.file.upload.UploadFile.uploadfile()
- python中的迭代器和生成器(一)——迭代器
- oracle中如何查看数据库服务器的ip地址
- 【索引】String
- datagridview 出错问题
- hadoop 集群及hbase集群的pid文件存放位置
- nil 和 releasse 作用
- 自定义语言的实现——解释器模式
- HDU 3001 Travelling ( 状态压缩 )
- hdu1875