Python序列迭代器设计原理与底层实现机制技术问询
Python 迭代器实现逻辑解答
你对迭代器节省内存的理解是正确的,所有内置类型的迭代器都不会拷贝原始对象的全量数据,仅维护遍历状态实现逐个取值,具体实现逻辑分类型说明如下:
序列类型(列表、字符串、元组)迭代器
这类支持随机访问的有序序列,迭代器内部会存储两个核心信息:
- 原始序列对象的强引用(逻辑等价于你所说的指向原始数据结构的指针)
- 当前遍历的位置索引(初始值为0)
每次调用__next__()方法或next()函数时,执行逻辑为:
- 校验当前索引是否小于序列总长度
- 校验通过则返回原始序列对应索引位置的元素,同时索引值+1
- 校验不通过则抛出
StopIteration异常,结束迭代
因为迭代器直接引用原始序列,若遍历过程中修改原始序列的元素值,迭代结果也会同步变化:
lst = [1, 2, 3] lst_iter = iter(lst) print(next(lst_iter)) # 输出 1 lst[1] = 999 print(next(lst_iter)) # 输出 999,而非修改前的2
映射类型(字典)迭代器
字典底层是哈希表结构,没有连续的数字索引,它的迭代器内部存储的信息为:
- 原始字典对象的强引用
- 哈希表当前遍历的槽位索引
- 字典版本号(用于校验遍历过程中字典结构是否发生变更)
迭代执行逻辑和序列类型类似,不过增加了版本校验:如果遍历过程中字典发生新增/删除键这类结构变更,版本号会发生变化,迭代器会直接抛出RuntimeError: dictionary changed size during iteration。Python 3.7+ 字典默认按插入顺序存储,所以迭代顺序和键的插入顺序完全一致。
默认状态下iter(dict)返回的是键迭代器,调用iter(dict.values())、iter(dict.items())会分别返回值迭代器、键值对迭代器,三者底层逻辑一致,仅返回的内容不同。
zip() 迭代器实现
Python 3 中zip()返回的迭代器属于组合式迭代器,实现逻辑如下:
- 初始化时会为每一个传入的可迭代对象生成对应的子迭代器,存储这些子迭代器的引用
- 每次调用
__next__()时,依次调用所有子迭代器的__next__()方法,把返回的结果打包成元组返回 - 只要任意一个子迭代器抛出
StopIteration,zip迭代器就会直接抛出StopIteration结束遍历,所以它的遍历长度和最短的输入可迭代对象一致 - 无参数调用
zip()时会直接返回空迭代器,第一次调用next()就会抛出StopIteration - 所有迭代器本身都是单次遍历的,因此
zip迭代器也仅支持单次遍历。
内容的提问来源于stack exchange,提问作者user17106369
相关产品推荐
相关产品推荐

