在字典中使用字符串作为键总是更快吗?

时间:2012-06-22 18:38:20

标签: python

在这个page上,我看到了一些有趣的东西:

请注意,dicts有一个快速路径(实际上)只处理str键;这不会影响算法的复杂性,但它会显着影响常数因素:典型程序的完成速度。

那究竟是什么意思呢?

这是否意味着使用字符串,因为键总是更快?

如果是,为什么?

更新

感谢有关优化的建议!但实际上,我对真实情况更感兴趣,而不是我们是否应该进行优化。

更新2:

感谢您的回答,我将引用@DaveWebb提供的link内容:

” ...

ma_lookup 最初设置为 lookdict_string 函数(在3.0中重命名为 lookdict_unicode ),该函数假设字典中的两个键都是被搜索的密钥是标准的PyStringObject。然后,它可以进行一些优化,例如减轻各种错误检查,因为字符串到字符串的比较从不引发异常。也不需要进行丰富的对象比较,这意味着我们避免调用 PyObject_RichCompareBool ,并且总是直接使用 _PyString_Eq

... “

另外,对于实验数字,我认为如果没有int-to-string转换,差异的大小会更大

2 个答案:

答案 0 :(得分:20)

作为String dict的基础的C代码对String键是最优的。 You can read about this here(在博客中提到的书中)。

如果Python运行时知道你的dict只包含字符串键,它可以做一些事情,例如不能满足字符串到字符串比较时不会发生的错误,并忽略丰富的比较运算符。这将使字符串键的常见情况仅dict更快一些。 (更新:时间显示它不止一点。)

但是,这不太可能对大多数Python程序的运行时间产生重大影响。如果您已经测量并发现dict查找是代码中的瓶颈,那么只关心此优化。 As the famous quote says, "Premature optimization is the root of all evil."

唯一可以看出事情真正有多快的方法就是计时:

>>> timeit.timeit('a["500"]','a ={}\nfor i in range(1000): a[str(i)] = i')
0.06659698486328125
>>> timeit.timeit('a[500]','a ={}\nfor i in range(1000): a[i] = i')
0.09005999565124512

因此,与int键相比,使用字符串键的速度提高约30%,我不得不承认我对差异的大小感到惊讶。

答案 1 :(得分:8)

因为这只影响恒定时间,所以根本不重要。您真正需要优化的唯一时间是在处理非常大的数据集时 - 这不会对此产生任何影响。

这意味着,如果你有一个字符串作为键的小字典,Python会很快 - 这是一个常见的用法,所以它已经过优化。

正如伊格纳西奥·巴斯克斯 - 艾布拉姆斯所指出的那样,将你的钥匙转换为字符串的成本可能远远超过你作为字典的字符串可能获得的微小提升。

简而言之,使用与您的情况相关的内容 - 优化只应在需要时进行,而不是之前。

一些测试:

python -m timeit -s "a={key: 1 for key in range(1000)}" "a[500]"
10000000 loops, best of 3: 0.0773 usec per loop

python -m timeit -s "a={str(key): 1 for key in range(1000)}" "a[\"500\"]"
10000000 loops, best of 3: 0.0452 usec per loop

python -m timeit -s "a={str(key): 1 for key in range(1000)}" "a[str(500)]"
1000000 loops, best of 3: 0.244 usec per loop

正如您所看到的,虽然基于字符串的字典更快,但相比之下转换密钥非常昂贵,完全可以减轻增益(然后是一些)。

所以,是的,如果您使用的数据被用作字典的键,以及存储它们的格式无关紧要,那么字符串更可取,在一个小字典中。在实践中,这是一种非常罕见的情况(你可能已经在使用字符串)。