如何在Python中从字典中删除一个项目?
在不修改原始字典的情况下,如何获得另一个已删除该项目的字典?
参见如何从Python字典中删除键?用于特定问题的相关信息,包括删除可能不存在的项目(通过键)。
如何在Python中从字典中删除一个项目?
在不修改原始字典的情况下,如何获得另一个已删除该项目的字典?
参见如何从Python字典中删除键?用于特定问题的相关信息,包括删除可能不存在的项目(通过键)。
pop
方法呢?实际上它的作用也是一样的吧?它不是更符合Python风格吗?(因为它是字典的方法,而不是特殊保留字) - Sergepop
返回被“弹出”的值,这样您就可以为任何进一步的原因使用该值。如果不是更符合 Python 风格,我肯定会说那似乎更好 :). 它不是字典,但对于两者都是以相同方式工作的:https://github.com/ivanlmj/python-prototypes/blob/master/3.4/pop_list.py - ivanleonczpop
更好,可以为其提供一个默认值,当字典中不存在该键时将返回该默认值。这对于需要删除一些键但其中某些键可能不存在的情况非常有用;在这种情况下,del
将会抛出 KeyError
异常。 - itachi我认为你的解决方案是最好的。但是如果你想要另一种解决方案,你可以创建一个新字典并使用旧字典的键,但不包括你指定的键,就像这样:
>>> a
{0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
>>> {i:a[i] for i in a if i!=0}
{1: 'one', 2: 'two', 3: 'three'}
{i:a[i] for i in a if i not in [0, 1, 2]}
,如果您想要删除多个元素。该语句的作用是创建一个字典,其中键为 a
中不在列表 [0, 1, 2]
中的元素 i
,值为 a[i]
。 - kmatheny{k:v for k,v in a.items() if k != 0}
。 - rlbond**kwargs
,则可以使用以下代码:some_function(**{k:v for k,v in some_dict.items() if k != 'some_key'})
- Cole有很多好的答案,但我想强调一件事。
您可以使用 dict.pop()
方法或更通用的del
语句 来从字典中删除项。它们都会改变原始字典,因此您需要复制它(请参阅下面的详细信息)。
如果传递给它们的键在字典中不存在,它们都会引发KeyError
:
key_to_remove = "c"
d = {"a": 1, "b": 2}
del d[key_to_remove] # Raises `KeyError: 'c'`
andkey_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)
和
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]
和
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
。
尽管使用del
与in
检查可能会略微更快,因为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}
您需要的是 del 语句。如果您有一个名为 foo 的字典,并且其具有一个名为 'bar' 的键,您可以按以下方式从 foo 中删除 'bar':
del foo['bar']
请注意,这会永久修改正在操作的字典。如果您想保留原始字典,您需要先创建一个副本:>>> foo = {'bar': 'baz'}
>>> fu = dict(foo)
>>> del foo['bar']
>>> print foo
{}
>>> print fu
{'bar': 'baz'}
dict
函数会创建一个浅层次的复制。如果你想要深层次的复制,请使用 copy.deepcopy
。
以下是一个可以复制粘贴的方法,供您方便使用:
def minus_key(key, dictionary):
shallow_copy = dict(dictionary)
del shallow_copy[key]
return shallow_copy
>>>
?是的,Python文档包含很多这样的内容。但是这种代码对于复制和粘贴来说并不方便。我感到困惑... - maxkoryukov>>>
模仿了 Python 在 cli 模式下的监听符号。 - pythonian29033>>>
。是的,它是REPL风格,但让我们坦白地说:只有一个人写了这个样本,而1000人阅读了。我认为,以易于复制和运行的方式编写示例将是很棒的。我不喜欢手动删除这些尖括号。或逐行复制..所以我不明白:为什么这些角度还在那里)))也许我不知道些什么? - maxkoryukovdict
是错误的数据结构。dict
相同,但“变异”API显然是不同的。最重要的是,Python中没有HATM电池。
pyrsistent
库是一个基于HAMT的字典替代方案(以及其他类型)的Python实现。它甚至还有一个巧妙的evolver API,可以尽可能平滑地将现有的可变代码移植到持久化代码中。但是,如果您想明确返回副本而不是进行变异,则只需像这样使用它:
>>> from pyrsistent import m
>>> d1 = m(a=1, b=2)
>>> d2 = d1.set('c', 3)
>>> d3 = d1.remove('a')
>>> d1
pmap({'a': 1, 'b': 2})
>>> d2
pmap({'c': 3, 'a': 1, 'b': 2})
>>> d3
pmap({'b': 2})
{{d3 = d1.remove('a')}}
如果您在{{pmap}}中嵌入了可变数据结构,如{{dict}}和{{list}},则仍会存在别名问题——您只能通过完全不可变来解决这个问题,嵌入{{pmap}}和{{pvector}}。
1. HAMTs在Scala、Clojure、Haskell等语言中也变得流行,因为它们与无锁编程和软件事务内存非常契合,但在Python中这些都不是很相关。
2. 实际上,stdlib中有一个HAMT,用于实现contextvars
。早期撤回的PEP解释了原因。但这是库的隐藏实现细节,而不是公共集合类型。
del rule['key_to_del']['nestedMapProp']
。 - undefinedd = {1: 2, '2': 3, 5: 7}
del d[5]
print 'd = ', d
结果:d = {1: 2,'2':3}
只需调用 del d['key']。
然而,在生产环境中,最好先检查 'key' 是否存在于 d 中。
if 'key' in d:
del d['key']
不,没有比这更好的方法。
def dictMinus(dct, val):
copy = dct.copy()
del copy[val]
return copy
然而,通常仅仅创建略有变化的字典副本可能不是一个好主意,因为这将导致相对较大的内存需求。通常更好的做法是记录旧字典(如果有必要),然后进行修改。
pop
方法会直接修改原字典,因此会改变从调用方传递给“辅助函数”的字典“引用”。因此,“辅助函数”不需要返回任何内容,因为调用方中原始字典的引用已经被修改。如果不需要返回值,请不要将dict.pop()
的返回值赋值给任何变量。例如:对my_dict进行某些操作; my_dict.pop(my_key, None); 对my_dict进行更多操作 # 现在没有了my_key
。如果需要,可以使用deepcopy(my_dict)
。 - Mark Mikofskid.pop(key)
。但是,如果有任何修改浅层副本的操作,就会出现众所周知的别名问题。如果你告诉我们更广泛的上下文,那么它就会很有帮助。(有没有其他东西改变了字典的值?你是否尝试对列表进行破坏性迭代?如果不是,那么你在做什么?) - smci