迭代器(iterator)是实现了迭代协议(Iteration Protocol)对象。迭代协议包括两个方法:
__iter__
,该方法返回一个迭代器, 可用于for循环;__next__
,该方法返回迭代器里下一个元素,并且一个元素只返回一次,当没有元素可返回时,引发一个StopIteration异常;
class Iterator_obj(object):
def __init__(self, start, end):
self.low = start
self.high = end
def __iter__(self):
return self
def next(self):
if self.low > self.high:
raise StopIteration
else:
self.low += 1
return self.low - 1
a = Iterator_obj(1, 10)
for i in a:
print i
迭代器遍历一次,一旦开始引起StopIteration异常,再调用next会一直引起该异常。
>>>a = Iterator_obj(1, 2)
>>>next(a)
1
>>>next(a)
2
>>>next(a)
Traceback (most recent call last):
File "", line 1, in
File "", line 11, in next
StopIteration
>>> next(c)
Traceback (most recent call last):
File "", line 1, in
File "", line 11, in next
StopIteration
注:python中的for循环其实是使用迭代器,转化成了while循环的方式使用的。
迭代器与可迭代对象是有区别的。可迭代对象是可以被for循环遍历的对象,比如列表、字符串,字典等,但是列表、字符串、字典却没有实现迭代器协议。
>>> a = [1, 2, 3]
>>> for i in a:
... print(i)
...
1
2
3
>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
列表并没有实现迭代器协议,但可以被for循环遍历
在python中,文件可以使用for循环遍历,实现了迭代器协议。在for循环对文件进行遍历的时候,它并不知道是在遍历文件,而是使用迭代器协议去访问访问对象。
>>> f = open('/etc/hosts')
>>> dir(f)
['__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'closed', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline', 'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines', 'xreadlines']
另外,python中许多内置函数也是通过迭代协议访问对象的。
标准库中的itertools模块使用迭代器的工具,下面是列举其中的几个:
chain--将多个迭代器连接成一个
>>> import itertools
>>> iter1 = iter([1, 2, 3])
>>> iter2 = iter([4, 5, 6])
>>> list(itertools.chain(iter1, iter2))
[1, 2, 3, 4, 5, 6]
izip--返回迭代器版本的zip
>>> for i,j in itertools.izip(x,y):
... print i, j
...
1 5
2 5
3 6
4 7
enumerate--以可迭代对象为参数,返回以数据源中(索引,取值)为元素的迭代器
>>> a = ["a","b","c"]
>>> for i, j in enumerate(a):
... print i, j
...
0 a
1 b
2 c