为什么遍历 dict 这么慢?
Why is iterating over a dict so slow?
我有一个脚本可以执行大量的字典删除并最终对其进行迭代。
我已经设法将其简化为一个简单的基准:
> py -m timeit -s "a = {i:i for i in range(10000000)};[a.pop(i) for i in range(10000000-1)]" "next(iter(a))"
10 loops, best of 5: 30.8 msec per loop
为什么在我删除了所有以前的值后迭代单个键变慢了?
从 3.6 开始,Python 字典使用内部散列 table 和 entries.
数组
当一个键从字典中删除时,它的条目实际上在数组中被替换为 dummy value 标记条目已删除。
迭代后,它会一个一个地跳过所有这些虚拟值,直到找到下一个真实项。
这就是为什么如果您跳过第一个值并仅删除其余值,您会发现迭代与迭代单个项目字典一样快:
> py -m timeit -s "a = {i:i for i in range(10000000)};[a.pop(i) for i in range(1,10000000-1)]" "next(iter(a))"
1000000 loops, best of 5: 219 nsec per loop
有关内部字典结构的更多信息,您可能会看到。
我有一个脚本可以执行大量的字典删除并最终对其进行迭代。
我已经设法将其简化为一个简单的基准:
> py -m timeit -s "a = {i:i for i in range(10000000)};[a.pop(i) for i in range(10000000-1)]" "next(iter(a))"
10 loops, best of 5: 30.8 msec per loop
为什么在我删除了所有以前的值后迭代单个键变慢了?
从 3.6 开始,Python 字典使用内部散列 table 和 entries.
数组当一个键从字典中删除时,它的条目实际上在数组中被替换为 dummy value 标记条目已删除。
迭代后,它会一个一个地跳过所有这些虚拟值,直到找到下一个真实项。
这就是为什么如果您跳过第一个值并仅删除其余值,您会发现迭代与迭代单个项目字典一样快:
> py -m timeit -s "a = {i:i for i in range(10000000)};[a.pop(i) for i in range(1,10000000-1)]" "next(iter(a))"
1000000 loops, best of 5: 219 nsec per loop
有关内部字典结构的更多信息,您可能会看到