Удаление элементов
Все способы удаления элементов из словаря Python: pop(), popitem(), del, clear() и генераторы словарей — с примерами и подводными камнями.
Словари Python — это изменяемые хранилища пар ключ–значение: вы можете добавлять, изменять и удалять записи в любое время. В этой главе рассматриваются все стандартные способы удаления элементов из словаря — pop(), popitem(), оператор del, clear() и генераторы словарей — с практическими замечаниями о том, когда лучше использовать каждый подход и как избежать распространённых ошибок.
Краткое сравнение
| Способ | Удаляет | Возвращает | Исключение при отсутствии ключа |
|---|---|---|---|
dict.pop(key) | Одну пару ключ–значение | Удалённое значение | KeyError (если не задано значение по умолчанию) |
dict.pop(key, default) | Одну пару ключ–значение | Удалённое значение или значение по умолчанию | Никогда |
dict.popitem() | Последнюю добавленную пару | Кортеж (key, value) | KeyError, если словарь пуст |
del dict[key] | Одну пару ключ–значение | Ничего | KeyError |
dict.clear() | Все пары | Ничего | Никогда |
| Генератор словаря | Выбранные пары | Новый словарь | Никогда |
Удаление одного элемента с помощью pop()
dict.pop(key) удаляет пару ключ–значение для указанного ключа и возвращает значение, которое там хранилось. Это удобно, когда нужно использовать значение для дальнейшей обработки после удаления.
Удалить ключ и сохранить его значение
Если ключ не существует, pop() вызывает исключение KeyError:
inventory = {'apples': 10}
inventory.pop('oranges') # KeyError: 'oranges'Использование значения по умолчанию для предотвращения KeyError
Передайте второй аргумент в pop() в качестве запасного значения. Если ключ отсутствует, pop() вернёт значение по умолчанию вместо того, чтобы вызывать исключение — словарь при этом останется без изменений.
Безопасное удаление с использованием значения по умолчанию
inventory = {'apples': 10, 'cherries': 20}
removed = inventory.pop('oranges', 0)
print(removed) # 0
print(inventory) # {'apples': 10, 'cherries': 20}Этот подход является удобной альтернативой проверке if key in dict перед вызовом pop().
Удаление последнего добавленного элемента с помощью popitem()
dict.popitem() удаляет и возвращает последнюю добавленную пару ключ–значение в виде кортежа (key, value). До того как в Python 3.7 был гарантирован порядок вставки, этот метод был основным инструментом для итеративного потребления словаря.
Извлечь последний добавленный элемент
scores = {'alice': 95, 'bob': 82, 'carol': 78}
last_item = scores.popitem()
print(last_item) # ('carol', 78)
print(scores) # {'alice': 95, 'bob': 82}popitem() вызывает KeyError, если словарь пуст. Используйте его, когда нужно последовательно обработать и потребить все элементы (как стек), или когда достаточно удалить только последнюю добавленную запись.
Удаление элемента с помощью del
Оператор del удаляет пару ключ–значение по ключу, не возвращая никакого значения. Используйте его, когда нужно просто удалить запись, не сохраняя удалённое значение.
Удалить ключ с помощью del
Как и pop() без значения по умолчанию, оператор del вызывает KeyError, если ключ отсутствует:
del user['phone'] # KeyError: 'phone'del против pop() — что выбрать?
- Используйте
del, когда нужно просто удалить элемент и значение вам не нужно. - Используйте
pop(), когда нужно получить удалённое значение или хотите безопасно обработать случай отсутствия ключа.
Удаление всех элементов с помощью clear()
dict.clear() очищает словарь на месте, оставляя пустой {}. Сам объект словаря при этом сохраняется, поэтому любая другая переменная, ссылающаяся на тот же словарь, также увидит пустой словарь.
Очистить все записи
config = {'host': 'localhost', 'port': 5432, 'debug': True}
config.clear()
print(config) # {}Сравните это с переприсваиванием config = {}: переприсваивание создаёт новый объект словаря, а все остальные ссылки по-прежнему указывают на старый (непустой). clear() изменяет тот же объект.
config = {'host': 'localhost', 'port': 5432}
alias = config # alias and config point to the same dict
config = {} # only config is updated; alias still has data
print(alias) # {'host': 'localhost', 'port': 5432}
config = {'host': 'localhost', 'port': 5432}
alias = config
config.clear() # modifies the shared object
print(alias) # {}Удаление нескольких конкретных ключей
В Python нет встроенного метода для одновременного удаления нескольких ключей, но существуют два идиоматических подхода.
Цикл с pop()
settings = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
to_remove = ['b', 'd']
for key in to_remove:
settings.pop(key, None) # None default = safe even if key is absent
print(settings) # {'a': 1, 'c': 3}Генератор словаря
Генератор словаря создаёт новый словарь, исключая ненужные ключи. Этот способ предпочтителен, когда нужно сохранить оригинал нетронутым.
Фильтрация словаря с помощью генератора
Можно также фильтровать по значению, а не по ключу:
scores = {'alice': 95, 'bob': 40, 'carol': 78, 'dan': 35}
passing = {name: score for name, score in scores.items() if score >= 50}
print(passing) # {'alice': 95, 'carol': 78}Удаление элементов во время итерации — распространённая ошибка
Изменение словаря во время итерации вызывает RuntimeError в Python 3:
data = {'a': 1, 'b': 2, 'c': 3}
# This raises RuntimeError: dictionary changed size during iteration
for key in data:
if data[key] < 2:
del data[key]Безопасный вариант — итерация по копии ключей:
data = {'a': 1, 'b': 2, 'c': 3}
for key in list(data): # list() snapshots the keys
if data[key] < 2:
del data[key]
print(data) # {'b': 2, 'c': 3}Альтернативно — создайте новый словарь с помощью генератора (как показано выше в разделе о генераторах) — зачастую это наиболее чистый подход.
Подробнее о безопасной итерации по словарям читайте в разделе Loop Dictionaries.
Выбор подходящего метода
- Нужно удалённое значение? Используйте
pop(key). - Ключ может отсутствовать? Используйте
pop(key, default), чтобы избежатьKeyError. - Просто удалить, значение не нужно? Используйте
del dict[key]. - Удалить последнюю добавленную запись? Используйте
popitem(). - Очистить всё? Используйте
clear(). - Удалить по условию или несколько ключей? Используйте генератор словаря или цикл
for key in list(dict).