Структура данных 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'] создаст ещё один defaultdict
defaultdict(<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())) решает проблему.

Словарь данных в Python - comments

En
словарь данных python (python)