'has_key()'或'in'?
我不知道什么是更好的做法:
d = {'a': 1, 'b': 2} 'a' in d True
要么:
d = {'a': 1, 'b': 2} d.has_key('a') True
in
肯定更pythonic。
实际上, has_key()
在Python 3.x中被删除了 。
不仅在优雅(而不是被弃用;-)而且在performance方面也是如此:
$ 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中,更快的解决scheme更加优雅,而Pythonic也是如此。 这就是为什么-mtimeit
是如此有用 – 这不仅仅是在这里和那里节省了一百纳秒 – )
根据python 文档 :
has_key()
被弃用,以支持key in d
的key in d
。
使用dict.has_key()
if(且仅当)您的代码需要可以在Python 2.3以前版本(引入key in dict
时)运行。
有一个例子, in
实际上杀死你的performance。
如果您in
仅使用__getitem__
和has_key()
而不是__contains__
的O(1)容器中使用,则会将O(1)search转换为O(N)search(如通过__getitem__
退回到线性search) 。
修复显然是微不足道的:
def __contains__(self, x): return self.has_key(x)
has_key
是一个字典方法,但是in
任何集合in
都可以工作,即使在__contains__
缺失的情况下,也会使用其他方法迭代集合来查找。
Python 2.x支持has_key()
。
Python 2.3+和Python 3.x支持。
dict.has_key()的解决方法已被废弃,请使用'in' – 崇高文本编辑器3
这里我举了一个名为“年龄”的字典的例子 –
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"
如果您的意图是使用默认值,以防钥匙不在字典中
my_dict.get('key') or default_value
是一种跳过检查的方式。 如果密钥不在字典中,则返回None
。 与使用in
一样,速度也是O(1)。
你也可以使用
my_dict.get('key', default_value)
但是我发现可读性较差。
Adam Parkin的评论扩展了Alex Martelli的性能testing
$ 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
该API看起来是这样做的一个原因…使用内置types的API作为logging是Pythonic …
您通常应该执行my_dict.get('key', default_value)
而不是my_dict.get('key') or default_value
。
奇怪的情况是希望用default_value
my_dict
从my_dict
返回的所有假等价值( 0
, ''
, []
等)。
实际上,如果打算从字典中获取默认值,为什么不使用collections.defaultdict
而不是内置dict
呢?
>>> from collections import defaultdict >>> d42 = defaultdict(lambda: 42) >>> d42['x'] = 18 >>> d42['x'] 18 >>> d42['y'] 42
defaultdicts最常见的用例可能是列表types,例如:
>>> dl = defaultdict(list) >>> for x, y in some_list_of_tuples: ... dl[x].append(y) >>>