如何从Python字典中删除键?


Answers:


2833

要删除键而不管它是否在字典中,请使用以下两个参数的形式dict.pop()

my_dict.pop('key', None)

my_dict[key]如果key字典中存在,则返回,None否则返回。如果第二个参数未指定(即my_dict.pop('key'))并且key不存在,KeyError则引发a。

要删除肯定存在的密钥,您还可以使用

del my_dict['key']

KeyError如果密钥不在字典中,则将引发a 。


152
有时使用pop()over 的好处del:它返回该键的值。这样,您可以在一行代码中从字典中获取和删除条目。
kratenko

7
在问题中,不需要保留该值。这只会增加不必要的复杂性。@zigg(如下)的答案要好得多。
Salvatore Cosentino

10
@SalvatoreCosentino我无法理解你的观点。这个答案中的代码比另一个答案中的代码如何复杂?
Sven Marnach

33
@SalvatoreCosentino不,忽略函数的返回值并不是完全没有效率的。恰恰相反- 如果键不存在,此解决方案比try/ except解决方案要快得多。您可能会发现其中一个更容易阅读,这很好。两者都是惯用的Python,因此请选择您喜欢的任何东西。但是声称这个答案更加复杂或效率低下根本没有道理。
Sven Marnach

5
@ user5359531我不明白。这怎么了?Python的内置类型上的所有方法均未返回self,因此,如果这样做的话,将是非常令人惊讶的。
Sven Marnach '18

352

专门回答“是否有一种统一的方法?”

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

...嗯,你问过 ;-)

你应该考虑,虽然,从删除对象的这种方式dict不是原子 -它是可能的,'key'可能是在my_dict该过程中if的语句,但是可以删除之前del被执行,在这种情况下del将失败,KeyError。鉴于此,最安全的使用dict.pop方式是

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

当然,这绝对不是单线的。


27
是的,pop虽然这样做有一个关键优势,但绝对是更简洁的方法:它可以立即清楚正在做什么。
zigg 2012年

4
try/except声明更昂贵。引发异常很慢。
克里斯·巴克

16
@ChrisBarker我发现如果密钥存在,try速度会稍微快一些,尽管如果不存在,try确实会慢很多。 pop是相当一致的,但是比try使用不存在的密钥要慢得多。参见gist.github.com/zigg/6280653。最终,这取决于您期望密钥实际出现在字典中的频率,以及是否需要原子性,当然还取决于您是否在进行过早的优化;)
zigg 2013年

9
我认为清晰度的价值不容忽视。为此+1。
Juan Carlos Coto 2014年

2
关于try / except的费用,您也可以去if 'key' in mydict: #then del...。我需要从字典中拉出键/值以正确解析,pop不是一个完美的解决方案。
2015年

152

我花了一些时间弄清楚究竟my_dict.pop("key", None)在做什么。因此,我将其添加为答案以节省其他Google搜索时间:

pop(key[, default])

如果key在字典中,请删除它并返回其值,否则返回default。如果未提供默认值并且字典中没有KeyError则引发a。

文献资料


15
只需在python解释器中输入help(dict.pop)即可。
David Mulder

13
当您需要了解某些功能时,help()和dir()可以成为您的朋友。
David Mulder

3
dict.pop?在IPython中。
Erik Kaplun 2014年

50

del my_dict[key]my_dict.pop(key)在键存在时从字典中删除键要快一些

>>> import timeit
>>> setup = "d = {i: i for i in range(100000)}"

>>> timeit.timeit("del d[3]", setup=setup, number=1)
1.79e-06
>>> timeit.timeit("d.pop(3)", setup=setup, number=1)
2.09e-06
>>> timeit.timeit("d2 = {key: val for key, val in d.items() if key != 3}", setup=setup, number=1)
0.00786

但是,当密钥不存在时,它会if key in my_dict: del my_dict[key]比稍快一点my_dict.pop(key, None)。两者都至少比快三倍deltry/ except语句:

>>> timeit.timeit("if 'missing key' in d: del d['missing key']", setup=setup)
0.0229
>>> timeit.timeit("d.pop('missing key', None)", setup=setup)
0.0426
>>> try_except = """
... try:
...     del d['missing key']
... except KeyError:
...     pass
... """
>>> timeit.timeit(try_except, setup=setup)
0.133

1
测量这样一个快速操作的时间非常愚蠢。您的代码可能不会更快,因为您将a更改popdel。创建字典将使从字典中删除内容完全相形见war。
鲍里斯

1
@鲍里斯-这对于一般练习很有用。
雏菊

1
@daisy我的意思是,你应该选择最可读的语法不就是300纳秒的速度运行(这是字面上的区别del,并pop从第一套以上定时)
鲍里斯

而且,这些操作是如此之快,以至于这些时序都不可靠。
鲍里斯

45

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

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}

或中的python3,您必须改为使用列表推导:

[myDict.pop(x, None) for x in ['a', 'c', 'e']]

有用。即使myDict没有“ e”键,“ e”也不会引起错误。


42
这在Python 3中将不起作用,因为mapandfriend现在很懒,并且返回了迭代器。使用map的副作用被普遍认为是不良的做法; 标准for ... in循环会更好。有关更多信息,请参见视图和迭代器而不是列表
格雷格·克里默

5
无论口味和实践风格如何,列表理解都应该在Py3中仍然有效[myDict.pop(i, None) for i in ['a', 'c']],因为它们提供了map(和filter)的通用替代方案。
Michael Ekoka

@MichaelEkoka您不应该将列表推导用于副作用,而应使用常规for ... in循环。
鲍里斯

@鲍里斯你可能是对的。我的回答特别涉及using map(),它经常因其副作用而使用。Python中推荐的替代方法列表理解,在我看来,列表理解仍然是一种可读性很强的单行代码(请参阅问题)。仅用于它们的副作用,这两种构造的确会导致无用的列表,这可能是低效的。从Python3开始,我还没有一个内置函数可以安全,优雅地遍历生成器表达式,而无需使用昂贵的副产品,例如loop(d.pop(k) for k in ['a', 'b'])
Michael Ekoka

我很开心,因为我历来最受推崇的答案包括一些我永远不会使用的技巧。我认为,列表理解(选项3)是最糟糕的方法。用那个。
Marc Maxmeister

19

您可以使用字典理解来创建新字典,并删除该键:

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

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



7

我们可以通过以下几种方法从Python字典中删除键。

使用del关键字;这几乎与您所采用的方法相同-

 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

myDict = {'one': 100, 'two': 200, 'three': 300, 'four': 400, 'five': 500}
{key:value for key, value in myDict.items() if key != 'one'}

如果我们在外壳中运行它,它将执行类似的操作{'five': 500, 'four': 400, 'three': 300, 'two': 200}-请注意,它与的顺序不同myDict。再次,如果我们尝试打印myDict,那么我们可以看到所有键,包括通过这种方法从字典中排除的键。但是,我们可以通过将以下语句分配给变量来创建新字典:

var = {key:value for key, value in myDict.items() if key != 'one'}

现在,如果我们尝试打印它,它将遵循父命令:

print(var) # {'two': 200, 'three': 300, 'four': 400, 'five': 500}

要么

使用pop()方法。

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()方法,我们实际上可以根据需要存储键的值,如下所示:

myDict = {'one': 100, 'two': 200, 'three': 300}
if myDict.get('one') : var = myDict.pop('one')
print(myDict) # {'two': 200, 'three': 300}
print(var)    # 100

如果您觉得有用,请叉要点以备将来参考。


1
不要if myDict.get('one')用来检查钥匙是否存在!如果myDict ['one']具有假值,则失败。另外,字典没有内在的顺序,因此提及它没有任何意义。
罗布

@Rob字典按插入顺序排序,从CPython 3.6开始,而所有其他Python实现从3.7开始。
鲍里斯

4

如果您想要非常冗长,可以使用异常处理:

try: 
    del dict[key]

except KeyError: pass

但是,pop()如果键不存在,这比方法要慢。

my_dict.pop('key', None)

几个键无关紧要,但是如果重复执行此操作,则后一种方法是更好的选择。

最快的方法是这样的:

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

但是此方法很危险,因为如果'key'在两行之间将其删除,KeyError则会引发a。


1

我更喜欢不变的版本

foo = {
    1:1,
    2:2,
    3:3
}
removeKeys = [1,2]
def woKeys(dct, keyIter):
    return {
        k:v
        for k,v in dct.items() if k not in keyIter
    }

>>> print(woKeys(foo, removeKeys))
{3: 3}
>>> print(foo)
{1: 1, 2: 2, 3: 3}

1

另一种方法是通过使用items()+ dict理解

items()结合dict理解也可以帮助我们完成键-值对删除的任务,但是它具有不适合就地使用dict的缺点。实际上,如果创建了一个新字典,除了我们不希望包含的密钥之外。

test_dict = {"sai" : 22, "kiran" : 21, "vinod" : 21, "sangam" : 21} 

# Printing dictionary before removal 
print ("dictionary before performing remove is : " + str(test_dict)) 

# Using items() + dict comprehension to remove a dict. pair 
# removes  vinod
new_dict = {key:val for key, val in test_dict.items() if key != 'vinod'} 

# Printing dictionary after removal 
print ("dictionary after remove is : " + str(new_dict)) 

输出:

dictionary before performing remove is : {'sai': 22, 'kiran': 21, 'vinod': 21, 'sangam': 21}
dictionary after remove is : {'sai': 22, 'kiran': 21, 'sangam': 21}

0

单键过滤

  • 如果my_dict中存在“ key”,则返回“ key”并将其从my_dict中删除
  • 如果my_dict中不存在“键”,则返回None

这将改变my_dict(可变)

my_dict.pop('key', None)

按键上有多个过滤器

生成一个新的字典(不可变的)

dic1 = {
    "x":1,
    "y": 2,
    "z": 3
}

def func1(item):
    return  item[0]!= "x" and item[0] != "y"

print(
    dict(
        filter(
            lambda item: item[0] != "x" and item[0] != "y", 
            dic1.items()
            )
    )
)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.