如何在Python中从字典中删除项目?

在不修改原始词典的情况下,如何获取删除了该项的另一个词典?


当前回答

没有,除了

def dictMinus(dct, val):
   copy = dct.copy()
   del copy[val]
   return copy

然而,通常只创建稍微修改过的字典的副本可能不是一个好主意,因为这会导致相对较大的内存需求。通常最好记录旧字典(如果需要),然后修改它。

其他回答

>>> def delete_key(dict, key):
...     del dict[key]
...     return dict
... 
>>> test_dict = {'one': 1, 'two' : 2}
>>> print delete_key(test_dict, 'two')
{'one': 1}
>>>

这不做任何错误处理,它假设密钥在dict中,您可能需要先检查它,如果没有,则引发

del语句删除一个元素:

del d[key]

请注意,这会改变现有的字典,因此字典的内容会对任何引用同一实例的其他人发生变化。要返回新词典,请复制词典:

def removekey(d, key):
    r = dict(d)
    del r[key]
    return r

dict()构造函数生成一个浅副本。要进行深度复制,请参阅复制模块。


注意,为每个dict del/assignment等制作一份副本。意味着你将从恒定时间变为线性时间,同时也使用线性空间。对于小字典来说,这不是问题。但是,如果您计划制作大量大型字典的副本,您可能需要一种不同的数据结构,如HAMT(如本答案所述)。

# mutate/remove with a default
ret_val = body.pop('key', 5)
# no mutation with a default
ret_val = body.get('key', 5)

没有,除了

def dictMinus(dct, val):
   copy = dct.copy()
   del copy[val]
   return copy

然而,通常只创建稍微修改过的字典的副本可能不是一个好主意,因为这会导致相对较大的内存需求。通常最好记录旧字典(如果需要),然后修改它。

有很多不错的答案,但我想强调一点。

您可以使用dict.pop()方法和更通用的del语句从字典中删除项。它们都会对原始词典进行变异,因此您需要制作一份副本(详见下文)。

如果你提供给他们的密钥不在字典中,他们两个都会引发KeyError:

key_to_remove = "c"
d = {"a": 1, "b": 2}
del d[key_to_remove]  # Raises `KeyError: 'c'`

and

key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove)  # Raises `KeyError: 'c'`

你必须注意这一点:

通过捕获异常:

key_to_remove = "c"
d = {"a": 1, "b": 2}
try:
    del d[key_to_remove]
except KeyError as ex:
    print("No such key: '%s'" % ex.message)

and

key_to_remove = "c"
d = {"a": 1, "b": 2}
try:
    d.pop(key_to_remove)
except KeyError as ex:
    print("No such key: '%s'" % ex.message)

通过执行检查:

key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
    del d[key_to_remove]

and

key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
    d.pop(key_to_remove)

但使用pop()还有一种更简洁的方法-提供默认返回值:

key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove, None)  # No `KeyError` here

除非您使用pop()获取要删除的键的值,否则您可以提供任何内容,而不是必需的None。尽管在check中使用del可能会稍微快一些,因为pop()是一个函数,其自身的复杂性会导致开销。通常情况并非如此,因此使用默认值的pop()就足够了。


至于主要问题,你必须复制你的字典,保存原来的字典,并在不删除密钥的情况下创建一个新字典。

这里的一些其他人建议使用copy.deepcopy()制作一个完整(深度)副本,这可能是一种过度的复制,使用copy.copy()或dict.copy()制作“普通”(浅)副本就足够了。字典保留对对象的引用作为键的值。因此,当您从字典中删除键时,将删除该引用,而不是被引用的对象。如果内存中没有其他对象的引用,则垃圾收集器稍后会自动删除对象本身。与浅拷贝相比,制作深度拷贝需要更多的计算,因此它通过制作拷贝、浪费内存和向GC提供更多的工作来降低代码性能,有时浅拷贝就足够了。

但是,如果您将可变对象作为字典值,并计划稍后在返回的字典中修改它们而不使用键,则必须进行深度复制。

使用浅拷贝:

def get_dict_wo_key(dictionary, key):
    """Returns a **shallow** copy of the dictionary without a key."""
    _dict = dictionary.copy()
    _dict.pop(key, None)
    return _dict


d = {"a": [1, 2, 3], "b": 2, "c": 3}
key_to_remove = "c"

new_d = get_dict_wo_key(d, key_to_remove)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3], "b": 2}
new_d["a"].append(100)
print(d)  # {"a": [1, 2, 3, 100], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2}
new_d["b"] = 2222
print(d)  # {"a": [1, 2, 3, 100], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2222}

使用深度副本:

from copy import deepcopy


def get_dict_wo_key(dictionary, key):
    """Returns a **deep** copy of the dictionary without a key."""
    _dict = deepcopy(dictionary)
    _dict.pop(key, None)
    return _dict


d = {"a": [1, 2, 3], "b": 2, "c": 3}
key_to_remove = "c"

new_d = get_dict_wo_key(d, key_to_remove)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3], "b": 2}
new_d["a"].append(100)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2}
new_d["b"] = 2222
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2222}