我应该使用'has_key()'或'in'在Python字典?

给定:

>>> d = {'a': 1, 'b': 2}

以下哪项是检查'a'是否在d中的最佳方法?

>>> 'a' in dTrue
>>> d.has_key('a')True
827343 次浏览

in肯定更Pythonic。

事实上#0在Python 3. x中被删除

根据python文档

has_key()不建议使用key in d.

in轻松获胜,不仅在优雅(并且不被弃用;-)方面,而且在性能方面,例如:

$ python -mtimeit -s'd=dict.fromkeys(range(99))' '12 in d'10000000 loops, best of 3: 0.0983 usec per loop$ python -mtimeit -s'd=dict.fromkeys(range(99))' 'd.has_key(12)'1000000 loops, best of 3: 0.21 usec per loop

虽然下面的观察不是总是真的,但你会注意到通常,在Python中,更快的解决方案更优雅和Pythonic;这就是为什么-mtimeit如此有用-它不是只是在这里和那里节省一百纳秒!-)

has_key是一个字典方法,但in可以在任何集合上工作,即使缺少__contains__in也会使用任何其他方法来迭代集合以找出答案。

如果(且仅当)您的代码需要可由2.3之前的Python版本运行(当引入key in dict时),请使用dict.has_key()

有一个例子,in实际上扼杀了你的表现。

如果您在O(1)容器上使用in,该容器仅实现__getitem__has_key()而不是__contains__,您将把O(1)搜索变成O(N)搜索(因为in通过__getitem__回退到线性搜索)。

Fix显然是微不足道的:

def __contains__(self, x):return self.has_key(x)

不建议使用dict.has_key()的解决方案,请使用'in'--sublime文本编辑器3

这里我举了一个名为“age”的字典的例子——

ages = {}
# Add a couple of names to the dictionaryages['Sue'] = 23
ages['Peter'] = 19
ages['Andrew'] = 78
ages['Karren'] = 45
# use of 'in' in if condition instead of function_name.has_key(key-name).if 'Sue' in ages:
print "Sue is in the dictionary. She is", ages['Sue'], "years old"
else:
print "Sue is not in the dictionary"

通过Adam Parkin的评论扩展Alex Martelli的性能测试…

$ python3.5 -mtimeit -s'd=dict.fromkeys(range( 99))' 'd.has_key(12)'Traceback (most recent call last):File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/timeit.py", line 301, in mainx = t.timeit(number)File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/timeit.py", line 178, in timeittiming = self.inner(it, self.timer)File "<timeit-src>", line 6, in innerd.has_key(12)AttributeError: 'dict' object has no attribute 'has_key'
$ python2.7 -mtimeit -s'd=dict.fromkeys(range(  99))' 'd.has_key(12)'10000000 loops, best of 3: 0.0872 usec per loop
$ python2.7 -mtimeit -s'd=dict.fromkeys(range(1999))' 'd.has_key(12)'10000000 loops, best of 3: 0.0858 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(  99))' '12 in d'10000000 loops, best of 3: 0.031 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(1999))' '12 in d'10000000 loops, best of 3: 0.033 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(  99))' '12 in d.keys()'10000000 loops, best of 3: 0.115 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(1999))' '12 in d.keys()'10000000 loops, best of 3: 0.117 usec per loop

如果你有这样的东西:

t.has_key(ew)

将其更改为在Python 3. X及更高版本上运行:

key = ewif key not in t