题 如何从Python字典中删除密钥?


当我试图从字典中删除一个键时,我写道:

if 'key' in myDict:
    del myDict['key']

有这样一种方式吗?


1051
2018-06-30 20:27


起源


针对此问题的答案中提出的各种方法的基准脚本: gist.github.com/zigg/6280653 - zigg


答案:


使用 dict.pop()

my_dict.pop('key', None)

这将返回 my_dict[key] 如果 key 存在于字典中,和 None 除此以外。如果未指定第二个参数(即。 my_dict.pop('key'))和 key 不存在,a KeyError 被提出来了。


1751
2018-06-30 20:29



有时使用的优​​势 pop() 过度 del:它返回该键的值。这样,您就可以在一行代码中从dict获取和删除条目。 - kratenko
在问题中,不需要保留该值。这只会增加不必要的复杂性。 @zigg(下面)的答案要好得多。 - Salvatore Cosentino
@SalvatoreCosentino我不能按照你的论点。这个答案中的代码比其他答案中的代码更复杂? - Sven Marnach
你好@SvenMarnach,1)我认为下面的答案更优雅(例如,处理异常)2)当你想存储删除的值时,使用大多数编程语言(和数据结构)中的'pop',问题只是要求删除密钥。返回一个从未使用过的值将是无效的。 - Salvatore Cosentino
@SalvatoreCosentino不,忽略函数的返回值根本不是低效的。恰恰相反 - 这个解决方案要快得多 try/except 解决方案,如果密钥不存在。您可能会发现其中一个或另一个更容易阅读,这很好。两者都是惯用的Python,所以选择你喜欢的任何东西。但声称这个答案更复杂或效率更低是没有意义的。 - Sven Marnach


特别要回答“有这样一种方式吗?”

if 'key' in myDict: del myDict['key']

......好吧,你  ;-)

但是,您应该考虑这种从一个对象中删除对象的方法 dict 是 不是原子的-它可能是 'key' 可能在 myDict 在此期间 if 声明,但可能会被删除 del 在这种情况下执行 del 会失败的 KeyError。鉴于此,这两者都是最安全的 使用 dict.pop 或类似的东西

try:
    del myDict['key']
except KeyError:
    pass

当然,这绝对是  单行。


262
2018-06-30 20:36



是啊, pop 虽然以这种方式做到这一点有一个关键优势,但它确实更简洁:它立即清楚它正在做什么。 - zigg
该 try/except 声明更贵。提出异常很慢。 - Chris Barker
@ChrisBarker我发现密钥是否存在, try 略微快一点,但如果没有, try 确实是一个很慢的交易。 pop 相当一致,但比所有的慢 try 使用非现有密钥。看到 gist.github.com/zigg/6280653。最终,它取决于你期望密钥实际出现在字典中的频率,以及你是否需要原子性 - 当然,还有你是否正在进行过早优化;) - zigg
我认为不应忽视清晰的价值。 +1为此。 - Juan Carlos Coto
关于尝试/除外的费用,你也可以去 if 'key' in mydict: #then del...。我需要从dict中取出一个key / val来正确解析,pop不是一个完美的解决方案。 - Marc


我花了一些时间才弄明白究竟是什么 my_dict.pop("key", None) 是在做。所以我将这个作为一个答案,以节省其他人的谷歌搜索时间:

pop(key [,default])

如果key在字典中,则删除它并返回其值,否则   返回默认值。如果没有给出默认值且密钥不在   字典,引发了一个KeyError

文档


115
2018-03-04 16:43



只需在python解释器中输入help(dict.pop)即可。 - David
当你需要知道什么是什么时,help()和dir()可以成为你的朋友。 - David
要么 dict.pop? 在IPython中。 - Erik Allik
此外,接受的答案有一个指向文档的链接(带有函数的锚点)。 - Michael


上述三种解决方案的时间安排。

小字典:

>>> import timeit
>>> timeit.timeit("d={'a':1}; d.pop('a')")
0.23399464370632472
>>> timeit.timeit("d={'a':1}; del d['a']")
0.15225347193388927
>>> timeit.timeit("d={'a':1}; d2 = {key: val for key, val in d.items() if key != 'a'}")
0.5365207354998063

较大的字典:

>>> timeit.timeit("d={nr: nr for nr in range(100)}; d.pop(3)")
5.478138627299643
>>> timeit.timeit("d={nr: nr for nr in range(100)}; del d[3]")
5.362219126590048
>>> timeit.timeit("d={nr: nr for nr in range(100)}; d2 = {key: val for key, val in d.items() if key != 3}")
13.93129749387532

25
2017-12-07 12:19



通常人们会写一个 conclusion 而不仅仅是倾销一些基准。 - user1767754


如果你需要在一行代码中从字典中删除很多键,我认为使用map()非常简洁,Pythonic可读:

myDict = {'a':1,'b':2,'c':3,'d':4}
map(myDict.pop, ['a','c']) # The list of keys to remove
>>> myDict
{'b': 2, 'd': 4}

如果您需要在弹出不在字典中的值时捕获错误,请在map()中使用lambda,如下所示:

map(lambda x: myDict.pop(x,None), ['a','c','e'])
[1, 3, None] # pop returns
>>> myDict
{'b': 2, 'd': 4}

有用。即使myDict没有'e'键,'e'也不会导致错误。


20
2017-09-16 19:17



这在Python 3中不起作用,因为 map 和朋友们现在懒惰并返回迭代器。运用 map 副作用通常被认为是不良做法;一个标准 for ... in 循环会更好。看到 视图和迭代器而不是列表 了解更多信息。 - Greg Krimer
无论品味和实践风格如何,列表推导仍应在Py3中运行 [myDict.pop(i, None) for i in ['a', 'c']],因为他们提供了一般的替代品 map (和 filter)。 - mike_e


使用:

>>> if myDict.get(key): myDict.pop(key)

其他方式:

>>> {k:v for k, v in myDict.items() if k != 'key'}

您可以按条件删除。如果没有错误 key 不存在。


14
2017-12-07 05:52



dict.has_key 在Python 3中删除了,相反,你应该使用 in (key in myDict)。您也应该在Python 2中执行此操作。 - Artyer
我特别喜欢使用字典理解的方式 - Matthias Herrmann


使用“del”关键字:

del dict[key]

5
2018-05-02 10:22



在dict中删除键的简洁解决方案 - Ajay Kumar