📜  为什么在Python迭代字典很慢?

📅  最后修改于: 2022-05-13 01:54:54.831000             🧑  作者: Mango

为什么在Python迭代字典很慢?

在本文中,我们将讨论为什么在Python迭代 dict 如此缓慢?在得出任何结论之前,让我们先看看PythonNumPy 数组和字典之间的性能差异:

Python
# import modules
import numpy as np
import sys
  
# compute numpy performance
def np_performance():
    array = np.empty(100000000)
    for i in range(100000000):
        array[i] = i
    print("SIZE : ", 
          sys.getsizeof(array)/1024.0**2, 
          "MiB")
  
# compute dictionary performance
def dict_performance():
    dic = dict()
    for i in range(100000000):
        dic[i] = i
    print("SIZE : ", 
          sys.getsizeof(dic)/1024.0**2, 
          "MiB")


Python3
# compute time taken
%time np_performance()


Python3
# compute time taken
%time dict_performance()


在上面的Python脚本中,我们有两个函数:

  1. np_performance:此函数为 10,00,000 个元素创建一个空的 NumPy 数组,并迭代整个数组,将单个元素的值更新为迭代器位置(在本例中为“i”)
  2. dict_performance:此函数为 10,00,000 个元素创建一个空字典,并迭代整个字典,将单个元素的值更新为迭代器位置(在本例中为“i”)

最后,调用sys.getsizeof()函数来计算各个数据结构的内存使用情况。

现在我们调用这两个函数,为了测量每个函数所花费的时间,我们使用%time函数,它为我们提供了Python语句或表达式的执行时间。 %time函数既可以用作线条魔法,也可以用作单元魔法:



  1. 在内联模式下,您可以对单行语句进行计时(尽管可以使用分号链接多个语句)。
  2. 在单元格模式下,您可以为单元格主体计时(紧随其后的语句会引发错误)。

使用 %time 方法从内联模式调用这些函数:

蟒蛇3

# compute time taken
%time np_performance()

输出:

蟒蛇3

# compute time taken
%time dict_performance()

输出:

正如我们所见,迭代 NumPy 数组和Python字典之间的 Wall time 存在很大差异。

  • 这种性能差异是由于数组和字典之间的内部工作差异造成的,因为在Python 3.6 之后, Python中的字典基于 HashTable 和元素数组的混合。因此,无论何时我们从字典中取出/删除一个条目,而不是从该特定位置删除一个键,它允许将下一个键替换为已删除键的位置。 Python字典所做的是用一个表示空的虚拟值替换哈希数组中的值。因此,当您遇到这些虚拟空值时,它会不断迭代,直到找到下一个实值键。
  • 由于可能有很多空白空间,我们将在没有任何实际好处的情况下遍历,因此字典通常比它们的数组/列表对应物慢。
  • 对于大型数据集,内存访问将是瓶颈。字典是可变的,并且比数组或(命名的)元组占用更多的内存(有效组织时,不复制类型信息)。