Как устроен словарь (dict) в Python?

Ответ

Словарь (dict) в Python — это изменяемая коллекция пар "ключ-значение", реализованная как хеш-таблица. С Python 3.7+ словари гарантированно сохраняют порядок вставки ключей. Это позволяет эффективно хранить и извлекать данные.

Ключевые особенности:

  • Ключи: Должны быть хешируемыми (т.е. неизменяемыми и иметь метод __hash__()). Примеры: str, int, float, tuple. Списки (list) и другие изменяемые объекты не могут быть ключами.
  • Значения: Могут быть любого типа и изменяемыми.
  • Производительность: Вставка, удаление и поиск элементов выполняются в среднем за O(1) (константное время), что делает словари очень эффективными для больших объемов данных.

Внутреннее устройство (хеш-таблица):

  1. Хеширование: Для каждого ключа вычисляется хеш-значение (целое число) с помощью хеш-функции.
  2. Индексирование: Хеш-значение используется для определения индекса (слота) в массиве, где будет храниться пара "ключ-значение".
  3. Коллизии: Если два разных ключа дают одинаковое хеш-значение (коллизия), Python использует механизм открытой адресации (или аналогичный) для поиска следующего свободного слота.

Пример использования:

# Создание словаря
person = {"name": "Alice", "age": 30, "city": "New York"}

# Доступ к значению
print(f"Имя: {person['name']}") # Вывод: Имя: Alice

# Добавление нового элемента
person["occupation"] = "Engineer"
print(person) # {'name': 'Alice', 'age': 30, 'city': 'New York', 'occupation': 'Engineer'}

# Изменение значения
person["age"] = 31

# Удаление элемента
del person["city"]
print(person) # {'name': 'Alice', 'age': 31, 'occupation': 'Engineer'}

Важные нюансы и лучшие практики:

  • Порядок: С Python 3.7+ словари гарантированно сохраняют порядок вставки ключей. Это не относится к Python 3.6 (где это было побочным эффектом реализации) и более ранним версиям.
  • Безопасный доступ: Используйте метод .get(key, default_value) для доступа к элементам, чтобы избежать KeyError, если ключ отсутствует.
  • Итерация: Методы dict.keys(), dict.values(), dict.items() возвращают view-объекты, которые предоставляют динамический вид на содержимое словаря, а не создают полные списки, что экономит память.