迭代器(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