Answers:
in
绝对更pythonic。
keys()
只是字典中的类似集合的视图,而不是副本,x in d.keys()
O(1)也是如此。尽管如此,x in d
还是更加Pythonic。
x in d.keys()
必须构造和销毁一个临时对象,并完成所需的内存分配,在这里x in d.keys()
只是进行算术运算(计算哈希)并进行查找。请注意,d.keys()
它只是此长度的10倍左右,实际上还不是很长。我没有检查,但我仍然很确定它只是O(1)。
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
似乎也是O(1)。
使用dict.has_key()
如果(且仅当)你的代码是要求Python版本早于2.3(当为可运key in dict
介绍)。
有一个例子in
实际上会削弱您的表现。
如果你使用in
一个O(1)集装箱只实现__getitem__
和has_key()
而不是__contains__
你会变成一个O(1)搜索到O(N),搜索(如in
回落到通过线性搜索__getitem__
)。
修复显然是微不足道的:
def __contains__(self, x):
return self.has_key(x)
has_key()
是针对Python 2字典。in
/ __contains__
是正确使用的API;对于那些不可避免要进行全面扫描的容器,无论如何都没有has_key()
方法,如果有O(1)方法,那将是用例专用的,因此由开发人员来选择解决问题的正确数据类型。
has_key
是一个字典方法,但是in
可以在任何集合上使用,即使__contains__
丢失,in
也可以使用任何其他方法来迭代该集合以找出答案。
in
对range
对象进行测试实际上非常有效。不过,我不太确定它在Python 2上的效率xrange
。;)
__contains__
可以简单地计算一个值是否在范围内。
range
每次创建新实例的开销。使用单个预先存在的实例,在我看来,“范围内的整数”测试快约40%。
dict.has_key()的解决方案已弃用,请使用“ in”-sublime文本编辑器3
在这里,我举了一个名为“ age”的字典的例子-
ages = {}
# Add a couple of names to the dictionary
ages['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 main
x = 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 timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
d.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 = ew
if key not in t
t.has_key(ew)
返回。如果值不在字典中,则返回。而且,别名非常非常冗余。正确的拼写是。这是8年前公认的答案已经告诉您的。True
ew
key not in t
True
key = ew
if ew in t