Python - Iterator + Generator
迭代器
- Python 中一切皆对象,对象的抽象就是类,对象的集合为容器(列表、元组、字典、集合)
- 所有的容器都是可迭代的(iterable)
- 迭代器(iterator)提供了一个 next 的方法
- 得到容器的下一个对象,或者得到一个 StopIteration 的错误
- 可迭代对象,通过 iter() 函数返回一个迭代器(iterator),再通过 next() 函数实现遍历
for in
语句隐式化了该迭代过程
判断一个对象是否可迭代 - iter(obj) 或者 isinstance(obj, Iterable)
1 | from typing import Iterable |
生成器
- 生成器在很多常用语言中,并没有对应的模型
- 生成器是懒人版本的迭代器
- 在 Python 中,生成器的写法为使用小括号 -
(i for i in range(100_000_000))
- 生成器不会像迭代器那样占用大量内存,只有在被使用时才会调用
- 生成器在初始化的过程中,不需要运行一次生成操作,开销更小
无限生成
- 程序运行到 yield 时,程序会暂停在这里,然后跳出,跳到 next() 函数,后续的表达式
i ** k
即 next() 函数的返回值 - 每当 next(gen) 函数被调用时,暂停的程序恢复,从 yield 向下继续执行
- 局部变量 i 并没有被清除掉,而是会继续累加
- 迭代器是一个有限集合,而生成器是一个无限集合
给定一个 list 和指定数字,寻找数字在 list 中的位置
常规版本
1 | def index_normal(l, target): |
生成器版本 - 用更少、更清晰的代码实现相同的功能 - 少用魔术体操,反而增加阅读难度
1 | def index_generator(l, target): # 返回一个生成器,方法体为生成逻辑 |
给定两个序列,判定第一个是不是第二个的子序列
优雅版本
1 | def is_subsequence(a, b): |
详细版本
1 | def is_subsequence(a, b): |
(i in b)
1 | while True: |
all() - 判断一个迭代器的元素是否全部为 True
小结
容器、可迭代对象、迭代器、生成器
- 容器是可迭代对象,可迭代对象调用 iter() 函数,可以得到一个迭代器
- 迭代器通过 next() 函数来得到下一个元素,所以支持遍历
- 生成器是一个特殊的迭代器
- 使用生成器,可以使得代码更清晰,降低内存占用
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.