迭代器与生成器
在前面的魔术方法的表格中,出现了两个魔术方法:__iter__()
和__next__()
。通过这两个魔术方法的组合,可以将一个类创建成一个迭代器。其中__iter__()
方法需要返回一个可迭代对象,__next__()
需要返回被迭代的对象中的一个元素。
如果一个类只重写了__iter__()
,那么这个类可以被称为可迭代对象。如果一个类同时重写了__iter__()
和__next__()
方法,那么这个类可以被称为迭代器。由于生成器也是一个可迭代对象,所以如果要让一个类成为生成器,只需要重写__iter__()
方法即可。以下通过三个示例来分别展示将类书写为不同的形式的方法。
可迭代对象
仅仅作为一个可迭代对象,类中的__iter__()
方法需要返回另一个可迭代的对象。
class Collector:
_collect = []
def __iter__(self):
return self._collect
for i in Collector():
pass
示例中通过返回另一个可迭代对象,把这个类定义为了一个可迭代对象,可以直接用于iter()
函数或者for
循环。
如果在__iter__()
方法中使用yield
抛出一个值,那么这个类的实例就会变成一个生成器。
class Fib:
def __init__(self):
self.a, self.b = 0, 1
def __iter__(self):
while True:
yield self.a
self.a, self.b = self.b, self.a + self.b
for i in Fib():
pass
迭代器
如果要将可迭代对象扩展为迭代器,需要额外重写__next__()
方法,并且__iter__()
方法中需要返回类实例本身。
class Fib:
def __init__(self):
self.a, self.b = 0, 1
def __iter__(self):
return self
def __next__(self):
return_value = self.a
self.a, self.b = self.b, self.a + self.b
return return_value
这里需要注意的是,在__next__()
方法中不能使用yield
关键字抛出值,那样会导致next()
函数取得一个生成器对象,而不是一个值。