迭代器与生成器

在前面的魔术方法的表格中,出现了两个魔术方法:__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()函数取得一个生成器对象,而不是一个值。