在Python当中,可迭代对象扮演着重要的角色,in运算符作用于可迭代的对象,list等许多内置函数也以可迭代对象作为参数。
如果对象实现了__getitem__方法,那么对象就已经是可迭代的。当__iter__方法没有被实现的时候,Python会尝试按顺序读取元素来构造迭代器。
更Pythonic的实现方法是实现__iter__特殊方法,其返回一个可迭代的对象。我们可以在其中返回一个内置可迭代的对象,比如list或者set。
两者都是定义在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__返回新的迭代器。