Как устроены множества и словари под капотом?
В Python множества (set) и словари (dict) реализованы на основе хеш-таблиц с открытой адресацией. Это обеспечивает быстрый доступ к элементам в среднем за O(1), но под капотом происходят интересные вещи.
1. Хеш-таблица и хеш-функция
При добавлении элемента (или пары ключ–значение) Python вызывает функцию
hash()для получения целого хеша.Хеш используется для вычисления индекса в массиве (обычно через побитовые операции).
Если два объекта имеют одинаковый хеш (коллизия), Python ищет следующую свободную ячейку (метод открытой адресации).
2. Открытая адресация
Вместо хранения "цепочек" элементов в одной ячейке, Python просто ищет другое место в массиве по определённой схеме (linear probing).
Это быстрее для CPU, так как данные лежат в памяти компактно.
3. Динамическое расширение
При заполнении таблицы примерно на 2/3 Python автоматически увеличивает размер массива в 2 раза.
При расширении происходит рехеширование — перерасчёт позиций для всех элементов, чтобы сохранить эффективность поиска.
4. Словари (dict)
dict)Хранят ключи и значения в двух разных массивах:
Один массив — "ключи и метаданные" (ключ + хеш).
Второй массив — "значения".
Порядок вставки элементов сохраняется (с Python 3.7 — официально гарантировано).
Доступ к значению: вычисляется хеш ключа → ищется индекс → по индексу берётся значение.
5. Множества (set)
set)Очень похожи на
dict, но без массива значений.По сути, это словарь, где все значения — фиктивные (
Trueили специальный объект-заглушка).
6. Особенности
Ключи и элементы должны быть хешируемыми — то есть иметь неизменяемый
__hash__()и корректный__eq__().Хеш-таблицы чувствительны к качеству хеш-функции: плохой хеш → больше коллизий → замедление.
Памяти словари и множества используют больше, чем список, из-за пустых ячеек и метаданных.
Удалённые элементы физически остаются в таблице как "маркеры пустоты", чтобы не ломать поиск.
Last updated
Was this helpful?