流畅的Python读书笔记-第 14 章 可迭代的对象、迭代器和生成器

第 14 章 可迭代的对象、迭代器和生成器

14.2 可迭代的对象与迭代器的对比

使用 iter 内置函数可以获取迭代器的对象。

如果对象实现了能返回迭代器的iter 方法,那么对象就是可迭代的。

序列都可以迭代;实现了 getitem 方法,而且其参数是从零开始的索引,这种对象也可以迭代。

14.3 Sentence类第2版:典型的迭代器

1
2
迭代器是这样的对象:实现了无参数的 __next__ 方法,返回序列中的下一个元素;
如果没有元素了,那么抛出 StopIteration 异常。Python 中的迭代器还实现了__iter__ 方法,因此迭代器也可以迭代。
1
2
3
4
5
标准的迭代器接口有两个方法。
__next__
返回下一个可用的元素,如果没有元素了,抛出 StopIteration 异常。
__iter__
返回 self,以便在应该使用可迭代对象的地方使用迭代器,例如在 for 循环中。

迭代器无法还原

1
2
因为迭代器只需 __next__ 和 __iter__ 两个方法,所以除了调用 next() 方法,以及捕获 StopIteration 异常之外,没有办法检查是否还有遗留的元素。此外,也没有办法“还原”迭代器。
如果想再次迭代,那就要调用iter(...),传入之前构建迭代器的可迭代对象。传入迭代器本身没用,因为前面说过Iterator.__iter__方法的实现方式是返回实例本身,所以传入迭代器无法还原已经耗尽的迭代器。

可迭代对象与迭代器

1
2
可迭代的对象一定不能是自身的迭代器。也就是说,可迭代的对象必须实现__iter__ 方法,但不能实现 __next__ 方法。
另一方面,迭代器应该一直可以迭代。迭代器的 __iter__ 方法应该返回自身。

14.4 Sentence类第3版:生成器函数

  • 更符合python风格的可迭代对像创建
  • 使用生成器函数
    1
    2
    3
    生成器函数的工作原理

    只要 Python 函数的定义体中有 yield 关键字,该函数就是生成器函数。调用生成器函数时,会返回一个生成器对象。也就是说,生成器函数是生成器工厂。

函数返回值;调用生成器函数返回生成器;生成器产出或生成值。

14.5 Sentence类第4版:惰性实现

re.finditer 函数是 re.findall 函数的惰性版本,返回的不是列表,而是一个生成
器,按需生成 re.MatchObject 实例。如果有很多匹配,re.finditer 函数能节省大量
内存。

14.6 Sentence类第5版:生成器表达式

生成器表达式可以理解为列表推导的惰性版本:不会迫切地构建列表,而是返回一个生成器,按需惰性生成元素。

也就是说,如果列表推导是制造列表的工厂,那么生成器表达式就是制造生成器的工厂。

() 替换 []

14.7 何时使用生成器表达式

如果生成器表达式要分成多行写,我倾向于定义生成器函数,以便提高可读性。此外,生成器函数有名称,因此可以重用。

坚持原创技术分享,您的支持将鼓励我继续创作!