迭代器和可迭代对象

在Python当中,可迭代对象扮演着重要的角色,in运算符作用于可迭代的对象,list等许多内置函数也以可迭代对象作为参数。

getitem__和__iter

如果对象实现了__getitem__方法,那么对象就已经是可迭代的。当__iter__方法没有被实现的时候,Python会尝试按顺序读取元素来构造迭代器。

更Pythonic的实现方法是实现__iter__特殊方法,其返回一个可迭代的对象。我们可以在其中返回一个内置可迭代的对象,比如list或者set。

Iterable和Iterator

两者都是定义在abc(abstract class)模块当中的抽象类(我们不用显示的继承它们)。分别表示可迭代和迭代器,Iterable当中只有一个方法__iter__,实现了__iter__的对象就会被认为是Iterable的子类。Iterator是Iterable的子类,其多了一个方法__next__,我们通常使用Iterator来生成Iterable。值得注意的是Iterator类中并没有如同Java一样有hasNext类似的方法,在__next__方法当中,当迭代需要停止的时候,我们抛出StopIteration异常。在迭代器中的__iter__方法中,通常返回self,或者可以显式的继承abc.Iterator。

下面截取自《fluent Python》当中的一个例子:

RE_WORD = re.compile('\w+')

class Sentence:
    def __init__(self,text):
        self.text = text
        self.words = RE_WORD.findall(text)

    def __iter__:
        return SentenceIterator(self.words)

class SentenceIterator:
    def __init_(self,words):
        self.words = words
        self.index = 0

    def __next__
        try:
            word = self.words[self.index]
        except IndexError:
            raise StopIteration()
        self.index += 1
        return word

    def __iter__(self):
        return self

这里有一点需要注意的是直接将Setence实现为迭代器的子类(实现__next__)方法不是一种好的做法,我们必须要从可迭代对象当中得到相互独立的迭代器,每个迭代器需要保存自己的内部状态(上面的self.index),这是一种错误的做法,如上面的例子所示,正确的做法是在__iter__返回新的迭代器。