Приємних відповідей дуже багато, але я хочу наголосити на одному.
Для видалення елементів зі словника ви можете використовувати як dict.pop()метод, так і більш загальний delвислів . Вони обидва мутують оригінальний словник, тому вам потрібно зробити копію (див. Деталі нижче).
І обидва вони піднімуть a, KeyErrorякщо ключ, який ви їм надаєте, відсутній у словнику:
key_to_remove = "c"
d = {"a": 1, "b": 2}
del d[key_to_remove] # Raises `KeyError: 'c'`
і
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)
і
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}