Jest wiele fajnych odpowiedzi, ale chcę podkreślić jedną rzecz.
Możesz użyć zarówno dict.pop()
metody, jak i bardziej ogólnej del
instrukcji, aby usunąć elementy ze słownika. Obaj mutują oryginalny słownik, więc musisz zrobić kopię (zobacz szczegóły poniżej).
I oba podniosą, KeyError
jeśli klucz, który im podajesz, nie jest obecny w słowniku:
key_to_remove = "c"
d = {"a": 1, "b": 2}
del d[key_to_remove] # Raises `KeyError: 'c'`
i
key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove) # Raises `KeyError: 'c'`
Musisz się tym zająć:
przechwytując wyjątek:
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)
i
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)
poprzez sprawdzenie:
key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
del d[key_to_remove]
i
key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
d.pop(key_to_remove)
ale pop()
jest też o wiele bardziej zwięzły sposób - podaj domyślną wartość zwracaną:
key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove, None) # No `KeyError` here
O ile nie użyjesz go pop()
do odzyskania wartości klucza, możesz podać wszystko, co nie jest konieczne None
. Chociaż może się zdarzyć, że używanie del
z in
kontrolą jest nieco szybsze, ponieważ pop()
jest funkcją z własnymi komplikacjami powodującymi narzut. Zwykle tak nie jest, więc pop()
przy domyślnej wartości jest wystarczająco dobra.
Jeśli chodzi o główne pytanie, będziesz musiał zrobić kopię swojego słownika, aby zapisać oryginalny słownik i mieć nowy bez wyjmowania klucza.
Niektórzy inni ludzie sugerują tutaj wykonanie pełnej (głębokiej) kopii copy.deepcopy()
, która może być przesadą, „normalną” (płytką) kopią, używając copy.copy()
lub dict.copy()
, może wystarczyć. Słownik przechowuje odwołanie do obiektu jako wartość klucza. Kiedy więc usuniesz klucz ze słownika, odwołanie to zostanie usunięte, a nie odwołany do obiektu. Sam obiekt może zostać później automatycznie usunięty przez moduł wyrzucający elementy bezużyteczne, jeśli nie ma w nim innych odniesień. Wykonywanie głębokiej kopii wymaga więcej obliczeń w porównaniu z płytką kopią, więc zmniejsza wydajność kodu, tworząc kopię, marnując pamięć i zapewniając więcej pracy GC, czasami płytka kopia wystarcza.
Jeśli jednak masz zmienne obiekty jako wartości słownikowe i planujesz zmodyfikować je później w zwróconym słowniku bez klucza, musisz wykonać głęboką kopię.
Z płytką kopią:
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}
Z głęboką kopią:
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}