检查字典中是否已存在给定键

Mohan Gulati 2683 python dictionary

我想在更新密钥的值之前测试字典中是否存在密钥.我写了以下代码:

if 'key1' in dict.keys():
  print "blah"
else:
  print "boo"

我认为这不是完成这项任务的最佳方式.有没有更好的方法来测试字典中的密钥?

Chris B... 2980

in是测试a中密钥是否存在的预期方法dict.

d = dict()

for i in range(100):
    key = i % 10
    if key in d:
        d[key] += 1
    else:
        d[key] = 1

如果您想要默认值,您可以随时使用dict.get():

d = dict()

for i in range(100):
    key = i % 10
    d[key] = d.get(key, 0) + 1

...如果您想始终确保可以defaultdictcollections模块中使用的任何键的默认值,如下所示:

from collections import defaultdict

d = defaultdict(int)

for i in range(100):
    d[i % 10] += 1

...但一般来说,in关键字是最好的方法.

  • 如果我打算将这个项目拉出字典,我通常只会使用`get`.使用`in`*和*将项目拉出字典是没有意义的. (66认同)
  • 我完全同意.但是,如果您只需要知道密钥是否存在,或者您需要区分定义密钥的情况和使用默认密钥的情况,那么"in"是最好的方法. (63认同)
  • 如果密钥等于"False",则get是一个错误的测试,例如`0`.很难理解:/ (24认同)
  • [参考](https://docs.python.org/3.4/library/stdtypes.html#dict)这个答案是在python docs (5认同)
  • 我不能同意这是一个完整的答案,因为它没有提到'尝试' - '除了'将是最快的,当密钥失败的数量足够小时.请参阅以下答案:/sf/ask/17360801/ (3认同)

Jason Baker.. 1479

您无需拨打密钥:

if 'key1' in dict:
  print "blah"
else:
  print "boo"

这会更快,因为它使用字典的散列而不是进行线性搜索,调用键就可以.

  • @Mohan Gulati:你明白字典是映射到值的键的哈希表,对吧?散列算法将密钥转换为整数,整数用于在散列表中查找匹配的位置.http://en.wikipedia.org/wiki/Hash_table (48认同)
  • ivan_bilan - 我刚刚在这个问题上进行了自己的测试......在50万个键上,"如果键入d1`则需要0.17265701293945312秒.调用`如果在d1.keys()中的键'采用`0.23871088027954102` - 这是微优化的经典定义.保存`0.07884883880615234`秒不是性能提升. (11认同)
  • @Eli为了你,我创造了一个你可以自己运行的测试.结果可能让你大吃一惊.对于带有~50,000个键的dicts,不调用`keys()`会给你0.01秒的计算好处.对于~500,000个键,不调用`keys()`会给你0.1秒的好处.对于~5,000,000个键,不调用`keys()`会快0.4秒,但对于50,000,000个键**调用`键()`IS 3 SECONDS FASTER!** (10认同)
  • 那样太好了.我的印象是它内部仍会遍历键列表,但我认为这更像是测试集合中的成员资格. (6认同)
  • @Charles Addis,根据使用大约五十万个键的经验,在写入"dict in key"而不是"key in dict.keys()"时,你获得至少10倍的性能提升.PEP和Zen还声明,如果它们对您的项目不利,您应该忽略它们. (5认同)
  • @Umimiku(及其他)。这是pycon 2010的非常有用的演示。您将看到,即使在小的记录集(<16个项目)中,冲突也会非常频繁地发生。但是python自动处理此问题。在字典中查找项目实际上与大小无关:http://pyvideo.org/pycon-us-2010/the-mighty-dictionary-55.html (2认同)

Michael Aaro.. 263

您可以使用in关键字测试字典中是否存在密钥:

d = {'a': 1, 'b': 2}
'a' in d # <== evaluates to True
'c' in d # <== evaluates to False

在变异之前检查字典中是否存在键的常见用法是默认初始化值(例如,如果您的值是列表,并且您希望确保存在可以追加的空列表插入键的第一个值时).在这种情况下,您可能会发现collections.defaultdict()感兴趣的类型.

在旧代码中,您还可以找到一些has_key()用于检查字典中键的存在的弃用方法(仅使用key_name in dict_name,而不是).

  • 想要分享(使用Python 2.7)我在很大程度上依赖于dict的内容的运行时间是使用“ key in dict.keys()”的363.235070,仅通过删除对“ keys( )” (2认同)

Greg Hewgill.. 95

你可以缩短这个:

if 'key1' in dict:
    ...

然而,这充其量只是一种美容改善.为什么你认为这不是最好的方法?

  • 这比化妆品改进更多*.使用此方法查找密钥的时间是O(1),而调用密钥将生成列表并且为O(n). (95认同)
  • 这是单个dict查找的复杂性,平均为O(1),最差为O(n)..list()将始终为O(n).https://wiki.python.org/moin/TimeComplexity (9认同)
  • O(1)似乎不太正确.你确定它不像O(log n)吗? (5认同)

Wtower.. 50

有关接受答案的建议方法(10米循环)的速度执行的其他信息:

  • 'key' in mydict 经过时间1.07秒
  • mydict.get('key') 经过时间1.84秒
  • mydefaultdict['key'] 经过时间1.07秒

因此使用indefaultdict建议使用get.

  • 完全同意`get`的1.84s <1.07*2 ;-P (4认同)

David Berger.. 48

我建议改用这种setdefault方法.听起来它会做你想要的一切.

>>> d = {'foo':'bar'}
>>> q = d.setdefault('foo','baz') #Do not override the existing key
>>> print q #The value takes what was originally in the dictionary
bar
>>> print d
{'foo': 'bar'}
>>> r = d.setdefault('baz',18) #baz was never in the dictionary
>>> print r #Now r has the value supplied above
18
>>> print d #The dictionary's been updated
{'foo': 'bar', 'baz': 18}

  • @hughdbrown"我想在更新密钥的值之前测试字典中是否存在密钥." 有时帖子包含的代码可以产生一些不完全是最初目标的响应.为了实现第一句中所述的目标,setdefault是最有效的方法,即使它不是发布的示例代码的替代品. (15认同)
  • "setdefault"与OP的问题有什么关系? (9认同)
  • 这是最好的答案,因为它满足了OP的目标,而不仅仅是提供技术上正确的答案.请参阅:http://nedbatchelder.com/blog/201207/bad_answers_on_stack_overflow.html (4认同)

mafonya.. 44

python中的字典有一个get('key',default)方法.所以你可以设置一个默认值,以防没有密钥.

values = {...}
myValue = values.get('Key', None)


HungryArthur.. 30

如何使用EAFP(更容易请求宽恕而非许可):

try:
   blah = dict["mykey"]
   # key exists in dict
except KeyError:
   # key doesn't exist in dict

查看其他SO帖子:

在python或中使用try vs if

检查Python中的成员是否存在

  • 如果密钥通常不存在,则尝试/除可能更昂贵.从你引用的帖子开始:"[我]你希望99%的时间结果实际上包含一些可迭代的东西,我会使用try/except方法.如果异常真的很特殊,它会更快.如果结果是None超过50%的时间,然后使用if可能更好.[...] [A]如果语句总是花费你,它几乎可以自由设置一个try/except块.但是当一个Exception实际发生时,成本要高得多." http://stackoverflow.com/a/1835844/1094092 (12认同)

Charitoo.. 25

使用三元运算符:

message = "blah" if 'key1' in dict else "booh"
print(message)


Bishwas Mish.. 17

您可以获得结果的方式是:

哪个更好取决于3件事:

  1. 字典'通常是否有密钥'或'通常没有密钥'.
  2. 你是否打算使用if ...... else ...... elseif ...... else等条件?
  3. 字典有多大?

阅读更多:http://paltman.com/try-except-performance-in-python-a-simple-test/

使用try/block而不是'in'或'if':

try:
    my_dict_of_items[key_i_want_to_check]
except KeyError:
    # Do the operation you wanted to do for "key not present in dict".
else:
    # Do the operation you wanted to do with "key present in dict."

  • 很好,但是需要针对python 3实现。我使用`2to3`转换了网页脚本,并且发现即使try键位于dict中,不带try语法总是比带try语法更快。 (2认同)

小智.. 16

您可以使用has_key()方法:

if dict.has_key('xyz')==1:
    #update the value for the key
else:
    pass

或者in如果找不到则设置默认值的方法:

if dict.has_key('xyz')==1:
    #update the value for the key
else:
    pass

  • `.has_key()`已经[已弃用](http://docs.pythonsprints.com/python3_porting/py-porting.html#replacing-dict-has-key); 你应该使用`in`,如其他答案所示. (20认同)
  • 顺便说一句,我建议在回答之前阅读******现有答案****OLD**问题.这个答案没有任何补充,因为这个建议已经存在于Michael的回答中,从'09开始.(我的意思是不鼓励尝试在讨论中添加有用的东西.继续尝试.) (12认同)

Mauricio Mor.. 15

只是一个FYI加入克里斯.B(最佳答案):

d = defaultdict(int)

也适用; 原因是调用int()返回0defaultdict幕后的(当构造字典时),因此文档中的名称为"Factory Function".

  • 如果你要创建一个计数字典,你应该使用[Counter](http://docs.python.org/2/library/collections.html#collections.Counter)(假设是Python 2.7).我使用`defaultdict(lambda:0)`而不是`defaultdict(int)`因为我认为它更清楚发生了什么; 如果你在没有参数的情况下调用`int()`,读者不需要知道你得到'0`.因人而异. (2认同)

prosti.. 6

检查字典中是否已存在给定键

为了了解如何做到这一点,我们首先检查可以在字典上调用的方法。方法如下:

d={'clear':0, 'copy':1, 'fromkeys':2, 'get':3, 'items':4, 'keys':5, 'pop':6, 'popitem':7, 'setdefault':8, 'update':9, 'values':10}

Python Dictionary clear()       Removes all Items
Python Dictionary copy()        Returns Shallow Copy of a Dictionary
Python Dictionary fromkeys()    Creates dictionary from given sequence
Python Dictionary get()         Returns Value of The Key
Python Dictionary items()       Returns view of dictionary (key, value) pair
Python Dictionary keys()        Returns View Object of All Keys
Python Dictionary pop()         Removes and returns element having given key
Python Dictionary popitem()     Returns & Removes Element From Dictionary
Python Dictionary setdefault()  Inserts Key With a Value if Key is not Present
Python Dictionary update()      Updates the Dictionary 
Python Dictionary values()      Returns view of all values in dictionary

检查密钥是否已存在的残酷方法可能是get()

d.get("key")

其他两种有趣的方法items()keys()听起来工作量太大。因此,让我们检查一下get()是否适合我们。我们有我们的字典d

d= {'clear':0, 'copy':1, 'fromkeys':2, 'get':3, 'items':4, 'keys':5, 'pop':6, 'popitem':7, 'setdefault':8, 'update':9, 'values':10}

打印显示我们没有的密钥将返回None

print(d.get('key')) #None
print(d.get('clear')) #0
print(d.get('copy')) #1

如果密钥存在或不存在,我们可能会用它来获取信息。但是,如果我们使用单个命令创建字典,请考虑以下问题key:None

d= {'key':None}
print(d.get('key')) #None
print(d.get('key2')) #None

get()如果某些值可能是,导致该方法不可靠None。这个故事的结局应该更快乐。如果我们使用in比较器:

print('key' in d) #True
print('key2' in d) #False

我们得到正确的结果。我们可以检查一下Python字节码:

import dis
dis.dis("'key' in d")
#   1           0 LOAD_CONST               0 ('key')
#               2 LOAD_NAME                0 (d)
#               4 COMPARE_OP               6 (in)
#               6 RETURN_VALUE

dis.dis("d.get('key2')")
#   1           0 LOAD_NAME                0 (d)
#               2 LOAD_METHOD              1 (get)
#               4 LOAD_CONST               0 ('key2')
#               6 CALL_METHOD              1
#               8 RETURN_VALUE

这表明in比较运算符不仅比更加可靠,而且甚至更快get()


归档时间:

查看次数:

3217588 次

最近记录:

1 年,5 月 前