Как работает словарь в Python
Вопрос
Расскажите, как устроен dict и почему поиск в нём быстрый. Что будет при плохой хеш-функции?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Хеш-таблица: ключ -> hash -> слот
Коллизии решаются открытой адресацией, ключи сравниваются через ==
Среднее O(1), худшее O(n), расширение при заполнении
Ключ должен быть хешируемым, хеш стабилен, равные объекты имеют равный хеш
Порядок вставки гарантирован с 3.7, компактное хранение
Рандомизация хеша строк защищает от атак на коллизии
Что могут спросить следом
- Что будет, если изменить объект, который уже лежит ключом?
- Почему нельзя менять размер словаря при итерации?
- Как сделать свой класс пригодным для ключа?
Разбор
Образцовый ответ: «dict это хеш-таблица. При вставке Python вычисляет hash(key), по младшим битам выбирает слот в таблице индексов, и если слот занят другим ключом, перебирает следующие по псевдослучайной последовательности проб, то есть открытая адресация. Найдя кандидата, сравнивает хеши, потом ключи через ==. Поэтому поиск в среднем O(1). Когда таблица заполняется примерно на две трети, её перестраивают в большую, это амортизируется. Сами записи CPython хранит в плотном массиве в порядке вставки, отсюда гарантированный порядок с 3.7 и экономия памяти. Требование к ключу: хешируемый, хеш не меняется, равные объекты дают равный хеш. Если положить объект ключом, а потом изменить поля, участвующие в хеше, ключ станет ненаходимым. При плохой хеш-функции, например все хеши одинаковые, словарь остаётся корректным, но вырождается в линейный поиск, и вставка n ключей стоит O(n²). На этом строили DoS, поэтому хеш строк в Python рандомизируется при каждом запуске».
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.