以下是Python文档中对于迭代器类型的描述
Python有一个在容器上进行迭代的概念。其实现需要两个方法来支持;这让用户自己定义的类也可以支持迭代。序列类型都支持迭代方法。
容器对象需要提供一个方法来提供对于迭代的支持:
container.__iter__():这个方法返回一个迭代器对象。这个对象必须支持后面所描述的迭代器协议。如果一个容器要支持不同类型的迭代,则可以提供额外的方法来专门为这些迭代类型请求相应的迭代器。(对象支持多种迭代形式的一个例子就是树数据结构中对广度优先和深度优先遍历的支持)。这个方法对应于Python/C API中Python对象类型结构体中的tp_iter字段。
迭代器对象自身必须具有如下两个方法,这两个方法一起就构成了迭代器协议:
iterator.__iter__()
返回迭代器对象自身。这是为了让容器和迭代器都能支持for和in语句。这个方法对应于Python/C API中Python对象类型结构体中的tp_iter字段。
iterator.__next__()
返回容器中的下一个元素。如果没有更多的元素了,就会抛出StopIteration异常。这个方法对应于Python/C API中Python对象类型结构体中的tp_iternext字段。
Python定义了几种迭代器对象来支持对常规和特定序列类型、字典和其它特殊类型的迭代。特定类型主要地,就是实现了迭代器协议而已。
一旦迭代器的__next__()方法抛出了StopIteration异常,随后的调用中也必须这样做。不遵守此种行为的情况被视为迭代器已损坏。
以上是文档中对迭代器类型相关的介绍,其中的核心就是迭代器对象——也就是实现了迭代器协议的对象。为此我们先根据文档中的说明定义自己的一个迭代器:
class SimpleIterator:
def __init__(self, max_index, position=0):
self._position = position
self._max = max_index
def __iter__(self):
return self
def __next__(self):
current_position = self._position
if current_position <= self._max:
self._position += 1
return current_position
else:
raise StopIteration
if __name__ == '__main__':
simple_iterator = SimpleIterator(100)
for item in simple_iterator:
print(item)
这是一个非常简单的迭代器,在其上迭代可以依次访问从初始化的position到max_index的所有整型数,并且是个闭区间(我在条件中使用了<=)。
现在我们实现了迭代器,如果想要让容器支持迭代器协议,按照上面文档的说法,就应该在一个容器内部定义一个__iter__()方法,并且要求其返回一个迭代器对象,我写了一个简单的支持迭代的容器类,它可以支持正序和反序迭代容器中的内容:
class ReverseIterator:
def __init__(self, seq=[]):
self._seq = seq
self._current_index = len(self._seq) - 1
def __iter__(self):
return self
def __next__(self):
if self._current_index < 0:
raise StopIteration
use_index = self._current_index
self._current_index -= 1
return self._seq[use_index]
class SimpleContainer:
def __init__(self, seq=[], reverse=False):
self._seq = seq
self._reverse = reverse
def __iter__(self):
if not self._reverse:
return iter(self._seq)
else:
return ReverseIterator(self._seq)
if __name__ == '__main__':
print("reverse=False")
simple_container = SimpleContainer([1, 2, 3], reverse=False)
for item in simple_container:
print(item)
print("reverse=True")
simple_container = SimpleContainer([1, 2, 3], reverse=True)
for item in simple_container:
print(item)
这里面,我使用了iter内置函数用来获取list类型的迭代器,用来支持默认的正序迭代;为了支持反序迭代,我自己实现了一个迭代器,根据容器的创建参数,容器的__iter__()方法会返回不同类型的迭代器,以支持不同类型的迭代。
最后,几点总结:
- __iter__()方法总是返回迭代器对象;
- __next__()方法需要在迭代器中返回下一个值;
- 迭代器对象中的__iter__()方法主要目的是为了让迭代器对象自身也支持for和in语句;
- 可以根据容器设置的条件,指定使用不同类型的迭代器;
- 要避免在迭代器协议实现的过程中复制底层容器对象(比如通过list[::-1]表达式来获取一个反序的新列表),防止内存资源浪费;
以上。