python函数迭代调用 python中的迭代法( 二 )


标准的迭代器接口有两个方法:
__next__ :返回下一个可用的元素 , 如果没有元素了,抛出 StopIteration 异常 。
__iter__ :返回 self,以便在需要使用可迭代对象的地方使用迭代器,如 for 循环中 。
迭代器:实现了无参数的 __next__ 方法,返回序列中的下一个元素;如果没有元素了,那么抛出 StopIteration 异常 。Python 中的迭代器还实现了 __iter__ 方法,因此迭代器也可以迭代 。
接下来使用迭代器模式实现 Sentence 类:
注意 ,  不要 在 Sentence 类中实现__next__方法,让 Sentence 实例既是可迭代对象 , 也是自身的迭代器 。
为了“支持多种遍历”,必须能从同一个可迭代的实例中获取多个独立的迭代器,而且各个迭代器要能维护自身的内部状态,因此这一模式正确的实现方式是,每次调用 iter(my_iterable) 都新建一个独立的迭代器 。
所以总结下来就是:
实现相同功能,但却符合 Python 习惯的方式是,用生成器函数代替 SentenceIteror 类 。
只要 Python 函数的定义体中有 yield 关键字,该函数就是生成器函数 。调用生成器函数,就会返回一个生成器对象 。
生成器函数会创建一个生成器对象,包装生成器函数的定义体,把生成器传给 next(...) 函数时,生成器函数会向前,执行函数定义体中的下一个 yield 语句,返回产出的值,并在函数定义体的当前位置暂停,。最终,函数的定义体返回时 , 外层的生成器对象会抛出 StopIteration 异常 , 这一点与迭代器协议一致 。
如今这一版 Sentence 类相较之前简短多了,但是还不够慵懒 。惰性,是如今人们认为最好的特质 。惰性实现是指尽可能延后生成值,这样做能节省内存,或许还能避免做无用的处理 。
目前实现的几版 Sentence 类都不具有惰性,因为__init__ 方法急迫的构建好了文本中的单词列表,然后将其绑定到 self.words 属性上 。这样就得处理整个文本,列表使用的内存量可能与文本本身一样多(或许更多 , 取决于文本中有多少非单词字符) 。
re.finditer函数是re.findall 函数的惰性版本,返回的是一个生成器,按需生成 re.MatchObject 实例 。我们可以使用这个函数来让 Sentence 类变得懒惰,即只在需要时才生成下一个单词 。
标准库提供了很多生成器函数,有用于逐行迭代纯文本文件的对象,还有出色的 os.walk 函数等等 。本节专注于通用的函数:参数为任意的可迭代对象,返回值是生成器,用于生成选中的、计算出的和重新排列的元素 。
第一组是用于 过滤 的生成器函数:从输入的可迭代对象中产出元素的子集,而且不修改元素本身 。这种函数大多数都接受一个断言参数(predicate),这个参数是个 布尔函数 ,有一个参数,会应用到输入中的每个元素上,用于判断元素是否包含在输出中 。
以下为这些函数的演示:
第二组是用于映射的生成器函数:在输入的单个/多个可迭代对象中的各个元素上做计算,然后返回结果 。
以下为这些函数的用法:
第三组是用于合并的生成器函数,这些函数都可以从输入的多个可迭代对象中产出元素 。
以下为演示:
第四组是从一个元素中产出多个值,扩展输入的可迭代对象 。
以下为演示:
第五组生成器函数用于产出输入的可迭代对象中的全部元素,不过会以某种方式重新排列 。
下面的函数都接受一个可迭代的对象,然后返回单个结果,这种函数叫“归约函数”,“合拢函数”或“累加函数”,其实,这些内置函数都可以用 functools.reduce 函数实现,但内置更加方便 , 而且还有一些优点 。

推荐阅读