python循环函数迭代 python循环方法( 二 )


接下来测试 Sentence 实例能否迭代
序列可以迭代的原因:
iter()
解释器需要迭代对象 x 时,会自动调用iter(x) 。
内置的 iter 函数有以下作用:
由于序列都实现了 __getitem__ 方法,所以都可以迭代 。
可迭代对象:使用内置函数 iter() 可以获取迭代器的对象 。
与迭代器的关系:Python 从可迭代对象中获取迭代器 。
下面用for循环迭代一个字符串,这里字符串 'abc' 是可迭代的对象,用 for 循环迭代时是有生成器,只是 Python 隐藏了 。
如果没有 for 语句,使用 while 循环模拟 , 要写成下面这样:
Python 内部会处理 for 循环和其他迭代上下文(如列表推导 , 元组拆包等等)中的 StopIteration 异常 。
标准的迭代器接口有两个方法:
__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),这个参数是个 布尔函数 ,有一个参数,会应用到输入中的每个元素上,用于判断元素是否包含在输出中 。

推荐阅读