Приємних відповідей дуже багато, але я хочу наголосити на одному.
Для видалення елементів зі словника ви можете використовувати як 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}