Структура данных dict в Python
Основы работы со словарями
Словарь (dict) в Python - это неупорядоченная коллекция элементов, где каждый элемент хранится в виде пары «ключ - значение». Ключи должны быть неизменяемыми (числа, строки, кортежи), значения могут быть любыми объектами. Словари реализованы как хеш-таблицы, что обеспечивает высокую скорость поиска, вставки и удаления.
Создание и базовые операции
Самый прямой способ - использовать фигурные скобки {} или встроенную функцию dict().
Как создать словарь с начальными значениями?
# Пустой словарь
d = {}
# Заполненный словарь
person = {
'name': 'Анна',
'age': 30,
'city': 'Москва'
}
# Через dict()
person2 = dict(name='Иван', age=25, city='СПб')
print(person)
print(person2)Python set list (set и list в python: различия и использование)
{'name': 'Анна', 'age': 30, 'city': 'Москва'}
{'name': 'Иван', 'age': 25, 'city': 'СПб'}Python пары значений (пары значений в python)
Обращение к элементу по ключу: person['name']. Если ключ отсутствует, возникнет ошибка KeyError. Для безопасного доступа используется метод .get(key, default).
print(person.get('country', 'Не указано'))Python object get (метод get для объектов в python)
Не указано
Python get keys (метод get для словарей в python)
Типичная ошибка:
Забыть, что ключ должен быть неизменяемым. Например, d[[1,2]] = 'value' вызовет TypeError: unhashable type: 'list'. Используйте кортеж.
Изменение и добавление элементов: присвоение значения по ключу.
person['age'] = 31 # изменение
person['job'] = 'Инженер' # добавление
print(person)Get index python (метод index в python)
{'name': 'Анна', 'age': 31, 'city': 'Москва', 'job': 'Инженер'}Python get methods (методы get в python)
Как избежать ошибок при отсутствии ключа?
Использование defaultdict
Класс defaultdict из модуля collections автоматически создаёт значение по умолчанию при обращении к отсутствующему ключу.
from collections import defaultdict
# Словарь, где по умолчанию - пустой список
word_groups = defaultdict(list)
words = ['cat', 'dog', 'cat', 'bird']
for w in words:
word_groups[w[0]].append(w)
print(dict(word_groups))Python длина списка (длина списка и массива в python)
{'c': ['cat', 'cat'], 'd': ['dog'], 'b': ['bird']}словарь данных python (словарь данных в python)
Возможные проблемы:
defaultdict при выводе всегда показывает все ключи, даже если они были созданы автоматически. При преобразовании в обычный dict (как выше) это не страшно. Также defaultdict наследует от dict, так что методы .keys() и другие работают.
Как сохранить порядок добавления элементов?
OrderedDict (Python 3.6 и ранее)
Начиная с Python 3.7, обычный словарь гарантирует порядок вставки. Для обратной совместимости или явного указания используйте OrderedDict.
from collections import OrderedDict
od = OrderedDict()
od['a'] = 1
od['b'] = 2
od['c'] = 3
print(od)
# Перемещение последнего элемента в начало
od.move_to_end('c', last=False)
print(od)типы данных python кортеж (кортеж (tuple) в python)
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
OrderedDict([('c', 3), ('a', 1), ('b', 2)])Python типы данных set (множество (set) в python)
Ошибка при использовании:
В Python 3.7+ OrderedDict избыточен, но его методы (например, move_to_end) полезны для явного управления порядком. Сравнение двух OrderedDict учитывает порядок, а обычных dict - нет.
Как подсчитать количество вхождений элементов?
Counter
Counter (из collections) - подкласс dict, специально созданный для подсчёта хешируемых объектов.
from collections import Counter
colors = ['red', 'blue', 'red', 'green', 'blue', 'blue']
cnt = Counter(colors)
print(cnt)
print(cnt.most_common(2))Counter({'blue': 3, 'red': 2, 'green': 1})
[('blue', 3), ('red', 2)]Типичная ошибка:
Считать Counter простым словарём. Метод .elements() возвращает элементы, повторяющие количество раз, а .most_common() требует аргумента.
Как объединить несколько словарей?
Оператор | (Python 3.9+), распаковка **, метод update
a = {'x': 1, 'y': 2}
b = {'y': 3, 'z': 4}
# Через |
merged = a | b
print(merged)
# Через ** (создаётся новый dict)
merged2 = {**a, **b}
print(merged2)
# Через update (изменяет a)
a.update(b)
print(a){'x': 1, 'y': 3, 'z': 4}
{'x': 1, 'y': 3, 'z': 4}
{'x': 1, 'y': 3, 'z': 4}При совпадении ключей значение берётся из второго словаря (справа).
Ошибка:
При использовании update исходный словарь изменяется. Если требуется сохранить оригинал, создавайте копию.
Как перебрать все элементы словаря?
Методы .items(), .keys(), .values()
d = {'a': 1, 'b': 2}
for key, value in d.items():
print(f'{key}: {value}')
for key in d.keys():
print(key)
for val in d.values():
print(val)a: 1 b: 2 a b 1 2
Не изменяйте размер словаря во время итерации (кроме Python 3) - это приведёт к RuntimeError: dictionary changed size during iteration.
Как удалить элемент из словаря?
del, .pop(), .popitem(), .clear()
d = {'a': 1, 'b': 2, 'c': 3}
del d['a'] # удаляет и вызывает ошибку, если нет ключа
value = d.pop('b') # возвращает значение и удаляет
print(value)
d.pop('x', None) # безопасно, если ключ отсутствует
last = d.popitem() # удаляет и возвращает последнюю пару (в Python 3.7+ - LIFO)
print(last)
d.clear()
print(d)2
('c', 3)
{}Частая ошибка:
Использовать del без проверки наличия ключа (if 'key' in d). Рекомендуется .pop() с умолчанием.
Как отсортировать словарь по ключам или значениям?
Функция sorted() с возвратом списка кортежей
d = {'banana': 3, 'apple': 5, 'cherry': 2}
sorted_by_key = dict(sorted(d.items()))
print(sorted_by_key)
sorted_by_value = dict(sorted(d.items(), key=lambda x: x[1]))
print(sorted_by_value){'apple': 5, 'banana': 3, 'cherry': 2}
{'cherry': 2, 'banana': 3, 'apple': 5}С Python 3.7 можно создать OrderedDict из отсортированных элементов для явного порядка.
Продвинутые примеры работы со словарями
1. Вложенные словари и авто-создание структуры
from collections import defaultdict
# Древовидная структура с автоматическим созданием levels
def tree():
return defaultdict(tree)
t = tree()
t['users']['alice']['age'] = 25
t['users']['bob']['city'] = 'London'
print(t)
# При обращении t['users']['charlie'] создаст ещё один defaultdictdefaultdict(<function tree at 0x...>, {'users': defaultdict(<function tree at 0x...>, {'alice': defaultdict(<function tree at 0x...>, {'age': 25}), 'bob': defaultdict(<function tree at 0x...>, {'city': 'London'})})})Пояснение:
Рекурсивный defaultdict позволяет создавать неограниченно вложенные структуры без явной проверки существования ключей. Это полезно для конфигураций, графов, сложных JSON-объектов.
2. Инвертирование словаря (ключи и значения меняются местами)
d = {'a': 1, 'b': 2, 'c': 1}
# Простое инвертирование (потеряет дублирующиеся значения)
inv_simple = {v: k for k, v in d.items()}
print('Простое:', inv_simple)
# Инвертирование с группировкой значений
from collections import defaultdict
inv_group = defaultdict(list)
for k, v in d.items():
inv_group[v].append(k)
print('С группировкой:', dict(inv_group))Простое: {1: 'c', 2: 'b'}
С группировкой: {1: ['a', 'c'], 2: ['b']}Пояснение:
Простое инвертирование подходит, если значения уникальны. В противном случае сохраняется только последнее сопоставление. Для сохранения всех ключей используется группировка списков.
3. Использование словаря в роли мемоизации (кэширование результатов)
def fib_memo(n, memo={}):
if n in memo:
return memo[n]
if n <= 1:
return n
memo[n] = fib_memo(n-1, memo) + fib_memo(n-2, memo)
return memo[n]
print(fib_memo(35))
print(fib_memo(100))9227465 354224848179261915075
Пояснение:
Словарь memo хранит уже вычисленные значения. Это сокращает экспоненциальное время до линейного. Важно: изменяемый аргумент по умолчанию - словарь - используется как кэш, общий для всех вызовов. Это нормально для данной задачи, но может быть неожиданным.
4. Словарь с ключами-кортежами для многомерных данных
# Координаты точек
points = {
(0, 0): 'центр',
(1, 0): 'право',
(0, 1): 'верх'
}
print(points[(0, 0)])
# Поиск всех точек с x=0
for (x, y), label in points.items():
if x == 0:
print(f'x=0, y={y}: {label}')центр x=0, y=0: центр x=0, y=1: верх
Пояснение:
Кортежи могут быть ключами, позволяя моделировать многомерные массивы или разреженные матрицы.
5. Генератор словарей с условием
original = {'a': 10, 'b': 25, 'c': 7, 'd': 42}
# Отфильтровать значения больше 20
filtered = {k: v for k, v in original.items() if v > 20}
print(filtered)
# Заменить значения на их квадраты для чётных
squared = {k: v**2 for k, v in original.items() if v % 2 == 0}
print(squared){'b': 25, 'd': 42}
{'a': 100, 'c': 49}Пояснение:
Dict comprehensions позволяют создавать новые словари на основе существующих с произвольными фильтрами и преобразованиями.
6. Словарь с методом setdefault для одношагового добавления
d = {}
# Без setdefault:
if 'group' not in d:
d['group'] = []
d['group'].append('apple')
# С setdefault:
d.setdefault('group', []).append('banana')
print(d){'group': ['apple', 'banana']}Пояснение:
setdefault возвращает значение по ключу, а если ключа нет, вставляет значение по умолчанию и возвращает его. Удобно для списков, множеств, счётчиков.
7. Сериализация словаря в строку с помощью json.dumps
import json
data = {'name': 'Python', 'version': 3.11, 'features': ['dict', 'list']}
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str){
"name": "Python",
"version": 3.11,
"features": ["dict", "list"]
}Пояснение:
Словари легко преобразовать в JSON. Обратное преобразование - json.loads. Важно: ключи должны быть строками, иначе json.dumps вызовет ошибку.
8. Обход словаря с одновременным удалением (копирование перед итерацией)
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# Удалить все чётные значения
for key in list(d.keys()): # копируем ключи
if d[key] % 2 == 0:
del d[key]
print(d){'a': 1, 'c': 3}Пояснение:
Изменение размера словаря во время итерации по его ключам запрещено. Копирование списка ключей (list(d.keys())) решает проблему.