Как устроен словарь в Python?
- Как работает dict внутри?
- Почему поиск в словаре работает за O(1)?
- Что может быть ключом словаря?
dict — хеш-таблица: по hash(key) находится место ключа, поиск в среднем за O(1).
- Ключ должен быть хешируемым и неизменным во время жизни
- Порядок вставки сохраняется (гарантировано с Python 3.7)
А ещё Упомяните коллизии и почему в худшем случае поиск O(n)
Подробно
При записи d[key] = value Python вычисляет hash(key) и по нему выбирает ячейку во внутренней таблице. При чтении происходит то же самое, и в ячейке сравниваются ключи: сначала хеши, затем ==. Поэтому поиск, вставка и удаление в среднем занимают O(1) и не зависят от размера словаря.
Коллизии. Разные ключи могут попасть в одну ячейку. CPython использует открытую адресацию: при занятой ячейке проверяет следующие по определённой последовательности. Когда таблица заполняется примерно на две трети, она увеличивается и элементы перераскладываются. В худшем случае, если хеши «плохие», поиск деградирует до O(n), но на практике это редкость.
Требования к ключу. Объект должен быть хешируемым: иметь __hash__, согласованный с __eq__ (равные объекты дают равный хеш), и хеш не должен меняться. Поэтому list, dict, set ключами быть не могут, а str, int, tuple из неизменяемых элементов, frozenset — могут.
Порядок. С Python 3.7 словарь гарантированно хранит ключи в порядке вставки: в CPython он устроен как компактный массив записей плюс отдельная таблица индексов.
Пример
d = {"a": 1}
d[(1, 2)] = "кортеж — можно"
d[[1, 2]] = "список" # TypeError: unhashable type: 'list'
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def __eq__(self, other):
return (self.x, self.y) == (other.x, other.y)
def __hash__(self):
return hash((self.x, self.y)) # согласован с __eq__Что хотят услышать
- Хеш-таблица и средняя сложность O(1).
- Требование хешируемости и связь
__hash__с__eq__. - Понимание коллизий и худшего случая.
- Сохранение порядка вставки с 3.7.
Частые ошибки
- «Словарь не упорядочен» — устаревшее утверждение.
- Переопределить
__eq__без__hash__: объект станет нехешируемым. - «Поиск всегда O(1)» без оговорки про средний случай.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Отсортированное дерево ключей: поиск за O(log n), порядок вставки теряется
- ✗Ключом может быть любой объект, включая список
- ✗Ключи хранятся в списке, поиск идёт перебором за O(n)
- ✓Хеш-таблица: место ключа ищется по hash(key), поиск в среднем O(1), ключ хешируемый
Что спросят дальше
Разбор темы
- Типы и коллекции — что изменяемо, что хешируемо и как устроен dict
Изменяемые и неизменяемые типы, список и кортеж, словарь и множество на хеш-таблице, is против ==, модуль collections.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.