How to remove a key from a Python dictionary?
当试图从字典中删除键时,我会写:
1 2
| if 'key' in myDict:
del myDict['key'] |
有一种单行的方法吗?
- 本问题答案中提出的各种方法的基准脚本:gist.github.com/zigg/6280653
使用dict.pop():
1
| my_dict.pop('key', None) |
如果字典中存在key,则返回my_dict[key],否则返回None。如果没有指定第二个参数(即my_dict.pop('key')且key不存在,则会引发KeyError。
- 有时使用pop()比del的优点是:它返回该键的值。这样,您可以在一行代码中从dict中获取和删除条目。
- 在问题中,不需要保留该值。这只会增加不必要的复杂性。@zigg(以下)的答案要好得多。
- @萨尔瓦托雷科森蒂诺,我听不懂你的论点。这个答案中的代码比另一个答案中的代码更复杂吗?
- 您好@svenmarnach,to 1)在我看来,下面的答案更优雅(例如,处理异常)2)当您想要存储删除的值时,在大多数编程语言(和数据结构)中使用"pop",而该问题只询问如何删除键。返回一个从未使用过的值是不有效的。
- @salvatorecosentino否,忽略函数的返回值并不是低效的。恰恰相反,如果密钥不存在,这个解决方案比try/except解决方案快得多。你可能会发现其中一个更容易阅读,这很好。两者都是惯用的python,所以选择您喜欢的任何一种。但是声称这个答案更复杂或效率更低根本没有意义。
- 这种方法的一个问题是它返回key的值,而不是原来的dict。因此,{'a':1, 'b':2}.pop('b')返回2,而不是{'a':1}。
- @用户5359531我不明白。这是怎么回事?python的内置类型中没有一个方法返回self,因此,如果这个方法返回self,那将是相当令人惊讶的。
- 当试图在列表理解中使用这个特性时,这对于Python中的一行程序来说是非常典型的用例。将一个听写列表转换为另一个已删除某些键的列表。
- @用户5359531通常应该避免使用带有副作用的列表理解,因为它们容易混淆。如果dict.pop()返回原来的dict,那么b = [d.pop("key") for d in a]将修改两个列表,a和b,因为它们都共享相同的字典对象。这就是为什么Python有一个约定,即改变方法没有返回值。(实际上,dict.pop()是本公约的一个例外,但并不违反公约精神。)
- @用户5359531如果您想在适当的位置改变字典列表,请使用for循环:for d in a: d.pop("key", None)。如果要保持原始词典不变,请先复制它们:b = [d.copy() for d in a]。
具体来说,回答"是否有一种单行的方法可以做到这一点?"
1
| if 'key' in myDict: del myDict['key'] |
…嗯,你问;-)
不过,您应该考虑,这种从dict中删除对象的方法不是原子的,可能在if语句期间'key'可能在myDict中,但在执行del之前可以删除,在这种情况下,del将失败,因为KeyError。考虑到这一点,使用dict.pop或其他类似的方法是最安全的。
1 2 3 4
| try:
del myDict['key']
except KeyError:
pass |
当然,这绝对不是一条直线。
- 是的,pop确实更简洁,不过这样做有一个关键的好处:很快就能清楚它在做什么。
- try/except声明的成本更高。引发异常很慢。
- @克里斯巴克,我发现如果钥匙存在,try的速度会稍微快一点,但如果没有,try的速度确实会慢很多。pop相当一致,但比除try以外的所有具有不存在密钥的密钥都慢。见gist.github.com/zigg/6280653。最终,这取决于您期望密钥在字典中的实际出现频率,以及您是否需要原子性,当然,还取决于您是否正在进行过早的优化;)
- 我相信清晰的价值不应该被忽视。为此加1。
- 关于试用费/除此之外,您也可以去1号店(22号店)。我需要从dict中提取一个key/val来正确解析,pop不是一个完美的解决方案。
- @但是,数据黑手党和所有的if k in d解决方案一样,这不是原子的,del可能会失败。为什么pop不为你工作?
- @Zigg我有一个不稳定的数据结构,简而言之,我需要通过嵌套在dict中的key/val对来订购dict。因此,我使用if key in来限定如果问题制造密钥在dict中,则复制到临时dict,执行dict的lambda/list comp排序,然后再添加值。在这种情况下,pop和del的工作原理是一样的。条件限定符允许将key/val放在temp dict中,以便进行排序。这是一个为一些棕地代码所做的工作,并不完美,但我们继续前进。pop()也可以,我喜欢冗长的del。尝试/捕获可能很贵。
- 尝试捕获是执行此操作的"正确方法"。这并不尴尬。
- @如果您需要处理一个键:值对,请使用popitem()。把它放入一个while循环来消耗整个dict。
我花了一段时间才弄清楚my_dict.pop("key", None)到底在做什么。因此,我将添加此作为一个答案,以节省其他人的谷歌时间:
pop(key[, default])
If key is in the dictionary, remove it and return its value, else
return default. If default is not given and key is not in the
dictionary, a KeyError is raised
文档
- 只需在python解释器中键入帮助(dict.pop)。
- 帮助()和dir()可以是你的朋友,当你需要知道某件事的作用时。
- 或伊普西顿的dict.pop?。
- 此外,接受的答案与文档有链接(带有指向函数的锚)。
上述三种解决方案的时间安排。
小词典:
1 2 3 4 5 6 7
| >>> 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 |
大字典:
1 2 3 4 5 6
| >>> 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 |
- 通常情况下,人们会写一个conclusion,而不是仅仅丢弃一些基准。
- 我将为用户1767754总结一下:del是从Python字典中删除键的最快方法
如果您需要在一行代码中从字典中删除大量键,我认为使用map()非常简洁,并且可以阅读pythonic:
1 2 3 4
| 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,如下所示:
1 2 3 4
| map(lambda x: myDict.pop(x,None), ['a','c','e'])
[1, 3, None] # pop returns
>>> myDict
{'b': 2, 'd': 4} |
它起作用了。"e"不会导致错误,即使mydict没有"e"键。
- 这在python 3中不起作用,因为map和friends现在很懒惰,返回迭代器。使用map作为副作用通常被认为是不好的做法;标准的for ... in循环会更好。有关详细信息,请参阅视图和迭代器而不是列表。
- 无论品味和实践风格如何,清单理解仍应在PY3-[myDict.pop(i, None) for i in ['a', 'c']]中有效,因为它们提供了map和filter的一般替代方案。
用途:
1
| >>> if myDict.get(key): myDict.pop(key) |
另一种方式:
1
| >>> {k:v for k, v in myDict.items() if k != 'key'} |
您可以按条件删除。如果key不存在,则无错误。
- 在python 3中删除了dict.has_key,而应该使用in(key in myDict)。在python 2中也应该这样做。
- 我特别喜欢使用字典理解的方法
- 第一个是明显错误的(如果键映射到None、空字符串或零,则不会删除),第二个则效率极低。
- 这是不正确的。如果myDict.get(key)恰好给出0、False或其他错误值,则不会删除密钥。
使用"del"关键字:
我们可以通过以下方法从python字典中删除一个键。
使用del关键字;这与您使用的方法几乎相同-
1 2 3 4
| myDict = {'one': 100, 'two': 200, 'three': 300 }
print(myDict) # {'one': 100, 'two': 200, 'three': 300}
if myDict.get('one') : del myDict['one']
print(myDict) # {'two': 200, 'three': 300} |
或
我们可以这样做:
但要记住,在这个过程中,实际上它不会从字典中删除任何键,而不会将特定键从字典中排除。此外,我发现它还返回了一个字典,它的顺序与myDict不同。
1 2
| myDict = {'one': 100, 'two': 200, 'three': 300, 'four': 400, 'five': 500}
{key:value for key, value in myDict.items() if key != 'one'} |
如果我们在shell中运行它,它将执行类似于{'five': 500, 'four': 400, 'three': 300, 'two': 200}的操作,注意它与myDict的命令不同。同样,如果我们尝试打印myDict,那么我们可以看到所有的键,包括我们用这种方法从字典中排除的键。但是,我们可以通过将以下语句赋给变量来创建新的字典:
1
| var = {key:value for key, value in myDict.items() if key != 'one'} |
现在,如果我们尝试打印它,那么它将遵循父顺序:
1
| print(var) # {'two': 200, 'three': 300, 'four': 400, 'five': 500} |
或
使用pop()方法。
1 2 3 4 5
| myDict = {'one': 100, 'two': 200, 'three': 300}
print(myDict)
if myDict.get('one') : myDict.pop('one')
print(myDict) # {'two': 200, 'three': 300} |
del和pop的区别在于,使用pop()方法,我们可以根据需要实际存储密钥的值,如下所示:
1 2 3 4
| myDict = {'one': 100, 'two': 200, 'three': 300}
if myDict.get('one') : var = myDict.pop('one')
print(myDict) # {'two': 200, 'three': 300}
print(var) # 100 |
如果你觉得这个有用的话,把这个要点交出来供将来参考。
- 不要用if myDict.get('one')来检查钥匙是否存在!如果mydict['one']的值错误,则失败。而且,听写没有固有的顺序,所以说它是没有意义的。