除了在python中使用`in` vs try的性能比较

时间:2015-04-08 19:02:55

标签: python performance dictionary

我在一些代码中有一个字典,它将一个键映射到一个单词,键是md5哈希的结果。我的代码基本上希望获得key的{​​{1}},当它不存在时,将其添加到字典中

这是我的第一个实现:

word

在分析我的代码后,我发现这非常慢。那么我试过这个,功能相同

key = int(hashlib.md5(word).hexdigest(), 16)
if key in self.id_to_word.keys():
    assert word == self.id_to_word[key]
else:
    self.id_to_word[key] = word
return key

结果令人难以置信的更快。虽然我对性能改进感到高兴,但我想知道是否有人可以向我解释原因。从类似的字典中检查key = int(hashlib.md5(word).hexdigest(), 16) try: assert word == self.id_to_word[key] return key except KeyError: self.id_to_word[key] = word 函数中的某些东西是不好的做法吗?它每次都会产生副本(浪费大量的计算)吗?

5 个答案:

答案 0 :(得分:3)

id_to_word.keys()创建一个新的列表,该列表是线性搜索的,比散列查找慢得多。删除.keys()

最快的方法是:

key = int(hashlib.md5(word).hexdigest(), 16)
assert word == self.id_to_word.setdefault(key, word)

答案 1 :(得分:2)

这是预期的(在python2中)。 keys()方法返回键的列表。因此,使用列表中的in运算符需要线性时间。

尝试访问该项是恒定时间,这要快得多。

注意:您只需使用key in dictionary代替try: ...except:


请注意,词典具有setdefault方法,已经可以执行您想要的操作。此外,如果您在很长一段时间内执行该操作,则应考虑使用collections.defaultdict而不是普通字典。

答案 2 :(得分:2)

key in some_dictkey in some_dict.keys()

快得多

Dict Lookup key in some_dict的复杂度为O(1)因此非常快

表示,如果密钥在dict中,它仍然(非常轻微)慢于try/except

真正的答案是这两种方法之间没有真正可衡量的差异,并且做对你感觉不错的事情

答案 3 :(得分:1)

阐述我上面的评论:

In [4]: d = {k:k for k in xrange(1000)}
In [5]: %timeit 50 in d
10000000 loops, best of 3: 68.6 ns per loop

In [6]: %timeit 50 in d.keys()
100000 loops, best of 3: 6.35 µs per loop

如您所见,使用d.keys()的速度大约慢100倍。

答案 4 :(得分:0)

如上所述,setdefault()解决了您的问题,但没有iftry阻止。
但是"更容易要求宽恕而不是许可" [EAFP]和鸭子打字是Python中常见的习惯用语,相比之下更具防御性的“先寻找你”#34; [LBYL]在其他语言中常见的习语,例如Java,C ++。

Jeff Knuth在其上发表了一篇有趣的博文Write Clean Python: Use Exceptions