Ci sono molte belle risposte, ma voglio sottolineare una cosa.
È possibile utilizzare sia il dict.pop()
metodo sia del
un'istruzione più generica per rimuovere elementi da un dizionario. Entrambi mutano il dizionario originale, quindi è necessario crearne una copia (vedere i dettagli di seguito).
Ed entrambi genereranno un KeyError
se la chiave che stai fornendo loro non è presente nel dizionario:
key_to_remove = "c"
d = {"a": 1, "b": 2}
del d[key_to_remove] # Raises `KeyError: 'c'`
e
key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove) # Raises `KeyError: 'c'`
Devi occuparti di questo:
catturando l'eccezione:
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)
e
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)
eseguendo un controllo:
key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
del d[key_to_remove]
e
key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
d.pop(key_to_remove)
ma con pop()
c'è anche un modo molto più conciso: fornisci il valore di ritorno predefinito:
key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove, None) # No `KeyError` here
A meno che non si utilizzi pop()
per ottenere il valore di una chiave rimossa, è possibile fornire qualsiasi cosa, non necessaria None
. Anche se potrebbe essere che l'utilizzo del
con in
check sia leggermente più veloce a causa della pop()
sua funzione con le sue complicazioni che causano spese generali. Di solito non è così, quindi pop()
con il valore predefinito è abbastanza buono.
Per quanto riguarda la domanda principale, dovrai fare una copia del tuo dizionario, per salvare il dizionario originale e averne uno nuovo senza che la chiave venga rimossa.
Alcune altre persone qui suggeriscono di fare una copia completa (in profondità) copy.deepcopy()
, che potrebbe essere eccessiva, una copia "normale" (superficiale), usando copy.copy()
o dict.copy()
, potrebbe essere sufficiente. Il dizionario mantiene un riferimento all'oggetto come valore per una chiave. Pertanto, quando si rimuove una chiave da un dizionario, questo riferimento viene rimosso, non l'oggetto a cui si fa riferimento. L'oggetto stesso può essere rimosso in seguito automaticamente dal Garbage Collector, se non ci sono altri riferimenti nella memoria. Realizzare una copia profonda richiede più calcoli rispetto alla copia superficiale, quindi diminuisce le prestazioni del codice effettuando la copia, sprecando memoria e fornendo più lavoro al GC, a volte è sufficiente una copia superficiale.
Tuttavia, se si hanno oggetti mutabili come valori di dizionario e si prevede di modificarli in un secondo momento nel dizionario restituito senza la chiave, è necessario effettuare una copia approfondita.
Con copia superficiale:
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}
Con copia profonda:
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}