迭代器 / Iteratior
目录
1 可迭代对象与迭代器协议
对于迭代器首先需要了解两个定义,迭代器协议 (Iterator Protocol) 与可迭代对象 (Iterable) ,
迭代器协议 Iterator Protocol:
迭代器协议是指对象能够提供 next() 方法 (__next__()) ,返回迭代中的下一项,或者引起一个 StopIteration 异常,以终止迭代。
可迭代对象 Iterable:
可迭代对象则是指,实现了迭代器协议的对象,例如 list、tuple、dict 等,这些都属于可迭代对象 (Iterable),但是却不是迭代器对象 (Iterator)。但可以使用内建函数 iter(),利用可迭代对象生成一个迭代器对象。
2 迭代器
对于迭代器来说,需要的是一个 __next__() 特殊函数,也就是迭代器与可迭代对象的一个重要差别。通过示例可以看到,可迭代对象是不具有 __next__() 方法的,而迭代器则有。
1 lis = [1, 2] 2 print(hasattr(lis, '__iter__')) # True 3 print(hasattr(lis, '__next__')) # False 4 lix = iter(lis) 5 print(hasattr(lix, '__iter__')) # True 6 print(hasattr(lix, '__next__')) # True
Note:
1. 内置函数 iter() 会调用对象的 __iter__() 方法,因此,可迭代对象具有 __iter__() 方法;
2. 内置函数 next() 会调用对象的 __next__() 方法,因此迭代器则需要具有 __next__() 方法;
3. 当 for 循环处理可迭代对象时,其本质是先调用了可迭代对象的 __iter__() 方法,使其变成迭代器后,再进行 next() 循环迭代。
利用 help 函数分别查看两个对象,
1 from collections import Iterator, Iterable 2 help(Iterator) 3 help(Iterable)
通过对迭代器的查看结果可以发现,Iterator 是以 Iterable 作为基类的,且多了一个 __next__() 方法。
class Iterable(builtins.object) | Methods defined here: | | __iter__(self) | | ---------------------------------------------------------------------- | Class methods defined here: | | __subclasshook__(C) from abc.ABCMeta | Abstract classes can override this to customize issubclass(). | | This is invoked early on by abc.ABCMeta.__subclasscheck__(). | It should return True, False or NotImplemented. If it returns | NotImplemented, the normal algorithm is used. Otherwise, it | overrides the normal algorithm (and the outcome is cached). | | ---------------------------------------------------------------------- | Data and other attributes defined here: | | __abstractmethods__ = frozenset({'__iter__'}) Help on class Iterator in module collections.abc: class Iterator(Iterable) | Method resolution order: | Iterator | Iterable | builtins.object | | Methods defined here: | | __iter__(self) | | __next__(self) | Return the next item from the iterator. When exhausted, raise StopIteration | | ---------------------------------------------------------------------- | Class methods defined here: | | __subclasshook__(C) from abc.ABCMeta | Abstract classes can override this to customize issubclass(). | | This is invoked early on by abc.ABCMeta.__subclasscheck__(). | It should return True, False or NotImplemented. If it returns | NotImplemented, the normal algorithm is used. Otherwise, it | overrides the normal algorithm (and the outcome is cached). | | ---------------------------------------------------------------------- | Data and other attributes defined here: | | __abstractmethods__ = frozenset({'__next__'})