# 迭代器模式 迭代是数据处理的基石。当扫描内存中放不下的数据时,我们就需要一种惰性获取数据项的方式,按需一次获取一个数据项,这就是迭代器模式(Iterator pattern)。 ## 迭代器和生成器 事实上,所有生成器都是迭代器,因为生成器完全实现了迭代器的接口。迭代器用来从集合中取出元素;而生成器用于凭空生成数据。即使是内置的`range()` 函数也是返回一个生成器对象。 ## 序列可迭代原理 解释器需要迭代序列对象时,会自动调用`iter()` 函数。内置的`iter()` 函数会进行一系列判断流程。 (1)检查对象是否实现了`__iter__` 方法,如果实现了就调用它,返回一个迭代器。 (2)如果没有实现`__iter__` 方法,但是实现了 `__getitem__` 方法,则会自动创建一个迭代器,尝试按顺序获取元素。 (3)如果尝试失败会抛出`TypeError` 异常,并且提示` object is not iterable` 。 ## 可迭代对象和迭代器的关系 从可迭代对象中获取迭代器。可迭代对象不是迭代器。可迭代对象可以迭代是因为实现了`__iter__` 方法或者`__getitem__` 方法;迭代器可以迭代,是因为实现了`__next__` 方法和`__iter__` 方法。可迭代对象不能是自身的迭代器,将可迭代对象构造成迭代器是不合理的。可迭代对象有必要实现`__iter__` 方法,但是不去实现 `__next__` 方法。 ## 迭代器接口 - `__next__`:返回下一个可用的元素,如果没有元素,抛出`StopIteration` 异常。 - `__iter__`:返回self,在使用迭代器的地方返回迭代器。 ## 生成器 使用关键字`yield` 修饰返回的对象,可以得到一个生成器。这个函数就是生成器函数,调用生成器函数返回一个生成器对象。 ## 惰性实现生成器 `re.finditer()` 函数是`re.findall()` 的惰性实现版本,返回的不是列表,而是一个生成器,按需生成`re.MacthObject` 实例。这样可以节省大量内存。 ## 生成器表达式 生成器表达式可以看作是列表推导式的惰性版本。 ## 等差数列生成器 内置的`range()` 函数常用于生成有穷整数等差数列,`itertools.count` 用于生成无穷等差数列。很多迭代器和生成器标准库`itertools` 模块中都已实现,不用重新发明轮子。 ## 常用生成器函数 `os.walk` 函数实际上返回的也是生成器,能够递归搜索文件系统。 ### 一、用于过滤的生成器函数 | 模块 | 函数 | 说明 | | --------- | ------------------------- | ------------------------------------------------------------ | | itertools | compress(it, selector_it) | 并行处理两个可迭代对象;如果selector_it中的元素为真值,产出it中对应的元素 | | itertools | dropwhile(predicate, it) | 处理 it,跳过 predicate 的计算结果为真值的元素,然后产出剩下的各个元素(不再进一步检查) | | 内置 | filter(predicate, it) | 把 it 中的各个元素传给 predicate,如果predicate(item) 返回真值,那么产出对应的元素;如果 predicate 是 None,那么只产出真值元素 | | itertools | | |