Python中可迭代对象、迭代器详解
这两个概念在Python中很容易混淆。第一个是可迭代对象(Iterable),二是迭代器(Iterator),三是生成器(Generator),暂且不谈生成器。

可迭代对象
列表、元组、字符串、字典等都是可迭代对象,所有元素都可以通过for循环遍历,称为可迭代对象(Iterable)。Iterable这一类是在Python的内置数据结构中定义的,在collections.在abc模块中,我们可以用这个来检测它是否是可迭代对象。
>>>fromcollectionsimportIterable >>>a=[1,2,3] >>>isinstance(a,Iterable) >>>True >>>b='abcd' >>>isinstance(b,Iterable) >>>True
这些数据结构之所以被称为Iterable,是因为它们的内部实现了__iter__()方法可以迭代。当我们使用for循环时,解释器将调用内置iter()函数,并在调用前检查对象是否已实现__iter__()方法,如果有,请调用它获取迭代器(接下来会说)。没有___加入iter__()方法,但实现了__getitem__()方法,解释器创建迭代器,并按顺序获取元素。如果没有找到这两种方法,Typeerror将被抛出异常。让我们定制对象,分别实现这两种方法(getitem(), iter())
classMyObj: def__init__(self,iterable): self._iterable=list(iterable) def__getitem__(self,item): returnself._iterable[item] obj=MyObj(1,2,3) foriinobj: print(i)
如上所示,这里没有实现__iter__方法,只实现___getitem__方法也使Myobj称为可迭代对象。
以下是____iter__方法,yield语法用于输出值(这里需要生成器的知识)
classMyObj: def__init__(self,iterable): self._iterable=list(iterable) def__iter__(self): index=0 whileTrue: try: yieldself._iterable[index] exceptIndexError: break index+=1 obj=MyObj(1,2,3) foriinobj: print(i)
在这里,对象也被称为可迭代对象。
相关推荐:Python视频教程
迭代器
迭代器是一个可以记住遍历位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有元素被访问结束。迭代器只能向前移动,不能向后移动。

如上图所示,迭代器(Iterator)继承可迭代(Iterable),必须实现迭代器______iter____________________next__方法。其中__next__方法用于输出下一个元素。
从继承图可以看出,迭代器必须是可迭代对象,可迭代对象不一定是迭代器。
迭代器有两种基本方法:iter() 和 next()。
我们使用iter(iterable)可以将可迭代对象转换为迭代器。
使用next(iterator)获取迭代器的下一个值。
>>>a=[3,4,5] >>>a >>>[3,4,5] >>>iter(a) >>><list_iteratorbjectat0x10ba8> >>>iterator=iter(a) >>>next(iterator) >>>3 >>>next(iterator) >>>4 >>>next(iterator) >>>5 >>>next(iterator) Traceback(mostrecentcalllast): File"<input>",line1,in<module> StopIteration
如上所示,由于对象已实现__next__方法,我们可以通过next(iterator)为了获得迭代器的下一个值,直到没有值,抛出StopIteration异常结束。
迭代器后面
迭代器Iterator是一个抽象基类,定义为_collections_abc.py中
Iterator源代码如下
classIterator(Iterable): __slots__=() @abstractmethod def__next__(self): 'Returnthenextitemfromtheiterator.Whenexhausted,raiseStopIteration' raiseStopIteration def__iter__(self): returnself @classmethod def__subclasshook__(cls,C): ifclsisIterator: return_check_methods(C,'__iter__','__next__') returnNotImplemented
可见,它已经实现了__subclasshook__方法,即Iterator不需要显式继承,只需要实现__iter__和__next__方法可以称为Iterator的虚拟子类。这里突出了Python的鸭子类型,实现特定的“协议”可以有一定的行为。
此外,它还定义了____iter__方法,当我们使用iter时(Iterator)直接回到自己身边,不做任何处理。
iter()函数的两种用法
在官方文件中给出了说明:
iter(iterable)->iterator iter(callable,sentinel)->iterator Getaniteratorfromanobject.Inthefirstform,theargumentmust supplyitsowniterator,orbeasequence. Inthesecondform,thecallableiscalleduntilitreturnsthesentinel.
第一种用法:iter(iterable) -> iterator (将可迭代对象转换为迭代器)
第二种用法:iter(callable, sentinel) -> iterator (第一个参数:任何可调用对象都可以是函数,第二个是标记值。当可调用对象返回此值时,迭代器抛出Stopiteration异常,而不输出标记值)
>>>fromrandomimportchoice >>>values=[1,2,3,4,6,7] >>>deftest_iter(): >>>returnchoice(values) >>>it=iter(test_iter,2) >>>it >>><callable_iteratorbjectat0x10b13000> >>>foriinit: >>>print(i) >>>7 >>>1 >>>7 >>>3 >>>1
以上代码流程:test_iter函数从values列表中随机选择一个值并返回,并调用iter(callable, sentinel)函数,将sentinel标记值设置为2,返回一个callable_iterator实例,遍历这个特殊的迭代器。如果函数返回标记值2,则直接抛出异常退出程序。这是iter函数的另一个鲜为人知的用法。
