python迭代器与iter()函数实例教程
- 发布时间:2014-07-16编辑:脚本学堂
迭代器是在版本 2.2 被加入 Python 的,它为类序列对象提供了一个类序列的接口。
序列是一组数据结构,你可以利用它们的索引从0 开始一直“迭代“ 到序列的最后一个条目。
用“计数“的方法迭代序列是很简单的。
Python 的迭代无缝地支持序列对象,而且它还允许程序员迭代非序列类型,包括用户定义的对象。
迭代器用起来很灵巧,可以迭代不是序列但表现出序列行为的对象,例如字典的 key,一个文件的行等。
当使用循环迭代一个对象条目时,几乎不可能分辨出它是迭代器还是序列。不必去关注这些,因为 Python 让它象一个序列那样操作。
如何迭代?
迭代器就是有一个 next() 方法的对象,而不是通过索引来计数。当你或是一个循环机制(例如 for 语句)需要下一个项时,调用迭代器的 next() 方法就可以获得它。条目全部取出后,会引发一个 StopIteration 异常,这并不表示错误发生,只是告诉外部调用者,迭代完成.
不过,迭代器也有一些限制。例如你不能向后移动,不能回到开始,也不能复制一个迭代器.如果你要再次(或者是同时)迭代同个对象,你只能去创建另一个迭代器对象。不过,这并不糟糕,因为还有其他的工具来帮助你使用迭代器。(www.jbxue.com 脚本学堂 整理)
reversed() 内建函数将返回一个反序访问的迭代器。enumerate() 内建函数同样也返回迭代器.另外两个新的内建函数,any() 和 all() ,在 Python 2.5 中新增,如果迭代器中某个/所有条目的值都为布尔真时,则它们返回值为真。本章先前部分展示了如何在 for 循环中通过索引或是可迭代对象来遍历条目。同时 Python 还提供了一整个 itertools 模块,它包含各种有用的迭代器.
一,使用迭代器
===序列===
正如先前提到的,迭代 Python 的序列对象和你想像的一样:
>>> i = iter(myTuple)
>>> i.next()
123
>>> i.next()
‘xyz’
>>> i.next()
45.67
>>> i.next()
Traceback (most recent call last):
File “<stdin>”,line 1,in <module>
StopIteration
如果这是一个实际应用程序,那么需要把代码放在一个 try-except 块中。序列现在会自动地产生它们自己的迭代器,所以一个 for 循环:
do_something_to(i)
实际工作方式:
不过不需要改动你的代码,因为 for 循环会自动调用迭代器的 next() 方法(以及监视StopIteration 异常)。
===字典===
字典和文件是另外两个可迭代的 Python 数据类型。字典的迭代器会遍历它的键(keys).
语句 for eachKey in myDict.keys() 可以缩写为 for eachKey in myDict ,例如:
… (‘Gaudi’,‘architect’): (1852,1906,1987),
… (‘Freud’,‘psychoanalyst’): (1856,1939,1990)
… }
…
>>> for eachLegend in legends:
… print ‘Name: %stOccupation: %s‘ % eachLegend
… print ‘ Birth: %stDeath: %stAlbum: %sn‘
… % legends[eachLegend]
…
Name: Freud Occupation: psychoanalyst
Birth: 1856 Death: 1939 Album: 1990
Name: Poe Occupation: author
Birth: 1809 Death: 1849 Album: 1976
Name: Gaudi Occupation: architect
Birth: 1852 Death: 1906 Album: 1987
另外,Python 还引进了三个新的内建字典方法来定义迭代:
myDict.iterkeys() (通过 keys 迭代),myDict.itervalues() (通过 values 迭代),以及 myDicit.iteritems() (通过 key/value 对来迭代)。(www.jbxue.com 脚本学堂 整理)
注意,in操作符也可以用于检查字典的 key 是否存在,之前的布尔表达式myDict.has_key(anyKey) 可以被简写为 anyKey in myDict。
===文件===
文件对象生成的迭代器会自动调用 readline() 方法。
这样循环就可以访问文本文件的所有行。程序员可以使用 更简单的 for eachLine in myFile 替换 for eachLine in myFile.readlines():
>>> for eachLine in myFile:
… print eachLine,# comma suppresses extra n
…
[EditorWindow]
font-name: courier new
font-size: 10
>>> myFile.close()
二,可变对象和迭代器
记住,在迭代可变对象的时候修改它们并不是个好主意。这在迭代器出现之前就是一个问题。
一个流行的例子就是循环列表的时候删除满足(或不满足)特定条件的项:
if not eachURL.startswith(‘http://’):
allURLs.remove(eachURL) # YIKES!!
除列表外的其他序列都是不可变的,所以危险就发生在这里。一个序列的迭代器只是记录你当前到达第多少个元素,所以如果你在迭代时改变了元素,更新会立即反映到你所迭代的条目上.在迭代字典的 key 时,你绝对不能改变这个字典。使用字典的 keys() 方法是可以的,因为keys() 返回一个独立于字典的列表。而迭代器是与实际对象绑定在一起的,它将不会继续执行下去:
>>> for eachKey in myDict:
… print eachKey,myDict[eachKey]
… del myDict[eachKey]
… a 1
Traceback (most recent call last):
File “<stdin>”,line 1,in <module>
RuntimeError: dictionary changed size during iteration
这样可以避免有缺陷的代码。更多有关迭代器的细节请参阅 PEP 234 .
三,如何创建迭代器
对一个对象调用 iter() 就可以得到它的迭代器。它的语法如下:
iter(obj)
iter(func,sentinel)
如果传递一个参数给 iter() ,它会检查你传递的是不是一个序列,如果是,那么很简单:
根据索引从 0 一直迭代到序列结束。另一个创建迭代器的方法是使用类,将在第 13 章详细介绍,一个实现了 __iter__() 和 next() 方法的类可以作为迭代器使用.
如果是传递两个参数给 iter() ,它会重复地调用 func ,直到迭代器的下个值等于sentinel。