为什么';在';python中以元组为键的运算符这么慢?

为什么';在';python中以元组为键的运算符这么慢?,python,dictionary,key,Python,Dictionary,Key,我的口述如下: d=dict() d[('1','2')] = 'value' 然后我查询密钥: if (k1,k2) in d.keys(): 当有一百万条记录时,速度很慢,“in”操作员有问题吗 是顺序搜索吗 我必须将str作为密钥来绕过这个问题。您应该使用 (k1,k2) in d 而不是调用d.keys() 按照您的方式执行,在Python 2中,将导致线性搜索,而不是否定dict的好处。在Python3中,您的代码是高效的(见下面的注释),但我的版本更清晰。考虑到Nolen Ro

我的口述如下:

d=dict()
d[('1','2')] = 'value'
然后我查询密钥:

if (k1,k2) in d.keys():
当有一百万条记录时,速度很慢,“in”操作员有问题吗

是顺序搜索吗

我必须将str作为密钥来绕过这个问题。

您应该使用

(k1,k2) in d
而不是调用
d.keys()


按照您的方式执行,在Python 2中,将导致线性搜索,而不是否定dict的好处。在Python3中,您的代码是高效的(见下面的注释),但我的版本更清晰。

考虑到Nolen Royalty的加入,我想我应该注意,您实际上可以以稍微更好的方式执行
timeit
测试。通过将
dict
的构造移动到一个设置函数中,我们可以只对
dict
上的操作计时,从而得到一个可以轻松比较的结果

在第3.2条中:

python -m timeit -s 'd = {(str(i), str(j)):"a" for i in range(100) for j in range(1000)}' '_ = ("1", "2") in d.keys()' '_ = (1, 2) in d.keys()'
1000000 loops, best of 3: 0.404 usec per loop

python -m timeit -s 'd = {(str(i), str(j)):"a" for i in range(100) for j in range(1000)}' '_ = ("1", "2") in d' '_ = (1, 2) in d'
1000000 loops, best of 3: 0.247 usec per loop
你可以看到区别。在3.x中,直接在
dict
上工作,速度几乎提高了2倍,这还不错

在2.7.3中:

python2 -m timeit -s 'd = {(str(i), str(j)):"a" for i in range(100) for j in range(1000)}' '_ = ("1", "2") in d.keys(); _ = (1, 2) in d.keys()'
10 loops, best of 3: 36.3 msec per loop

python2 -m timeit -s 'd = {(str(i), str(j)):"a" for i in range(100) for j in range(1000)}' '_ = ("1", "2") in d' '_ = (1, 2) in d'
10000000 loops, best of 3: 0.197 usec per loop
在2.x中,差异确实惊人。使用
dict.keys()
需要36300微秒,而仅使用
dict
不到0.2微秒。快了将近二十万倍

只是觉得值得一提

编辑:

蒂姆做了一个有趣的评论,所以我决定再做一次测试。我尝试构建列表,然后进行哈希查找,结果如下:

python2 -m timeit -s 'd = {(str(i), str(j)):"a" for i in range(100) for j in range(1000)}' 'd.keys()' 'd.keys()'
100 loops, best of 3: 5.84 msec per loop

python2 -m timeit -s 'd = {(str(i), str(j)):"a" for i in range(100) for j in range(1000)}' -s 'l=d.keys()' '_ = ("1", "2") in l' '_ = ("1", "2") in l'
10 loops, best of 3: 25.3 msec per loop

您可以看到,在这样一个大型dict上,构建列表大约需要六分之一的时间,搜索列表需要五分之六的时间。

您能告诉我们得出这个结论的代码吗?非常有趣的问题,我将对此进行研究。您的编辑引入了一个全新的问题:为什么不在单独的问题中提问?我想那会更有意义。我把问题推回原来的形式。如果你想问一个不同的问题,那就换一个新问题问吧。对不起,我是stackoverflow的新手。最后一次编辑是显示代码。这对Python2和Python3都适用吗?我以为
.keys()
会在Python 3中提供一个视图对象,而不是列表?我很难理解为什么有人会使用
d.keys()
。在Python2.x中,这将每次创建一百万条记录的列表。即使在3.x中,它仍然是完全冗余的。@TimPietzcker即使它创建了一个iterable视图对象,中的
操作符也必须执行线性搜索。您需要将
in
运算符应用于
dict
对象。@davidhefferan键的dict视图设置如下:,因此,它将具有与dict本身相同的性能。@DavidHeffernan-它们在Python 3中实际上非常灵活。很好-我很确定,这种巨大的差异主要不是因为线性搜索与哈希查找,而是因为每次迭代都构造了一个键列表,正如您在对@DavidHeffernan的回答的评论中所建议的那样。非常感谢您的提示,我不知道您可以轻松地通过这样的设置功能+1@NolenRoyalty这真的很有用-您还可以通过多次使用该标志进行多个设置。您还可以通过放置更多带引号的字符串来避免使用分号。使做复杂的测试更容易。@TimPietzcker事实上,我只是做了一个检查并编辑了我的答案以添加到我的结果中——大部分时间都花在搜索上。我必须承认,我认为创建列表将是最大的因素。(再说一次,我也没想到会有这么大的差别。)@Lattyware:哇。太好了,谢谢你把事情弄清楚。