第 14 章 可迭代的对象、迭代器和生成器
14.2 可迭代的对象与迭代器的对比
使用 iter 内置函数可以获取迭代器的对象。
如果对象实现了能返回迭代器的iter 方法,那么对象就是可迭代的。
序列都可以迭代;实现了 getitem 方法,而且其参数是从零开始的索引,这种对象也可以迭代。
14.3 Sentence类第2版:典型的迭代器
1 | 迭代器是这样的对象:实现了无参数的 __next__ 方法,返回序列中的下一个元素; |
1 | 标准的迭代器接口有两个方法。 |
迭代器无法还原
1 | 因为迭代器只需 __next__ 和 __iter__ 两个方法,所以除了调用 next() 方法,以及捕获 StopIteration 异常之外,没有办法检查是否还有遗留的元素。此外,也没有办法“还原”迭代器。 |
可迭代对象与迭代器
1 | 可迭代的对象一定不能是自身的迭代器。也就是说,可迭代的对象必须实现__iter__ 方法,但不能实现 __next__ 方法。 |
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 何时使用生成器表达式
如果生成器表达式要分成多行写,我倾向于定义生成器函数,以便提高可读性。此外,生成器函数有名称,因此可以重用。