(Примечание: я не очень хорошо знаком с внутренними компонентами реализации dict
Python, я говорю здесь о хеш-таблицах в целом.)
Основная идея хеш-таблицы заключается в том, что вы можете получитьхеш-значение из ключа, и используйте его, чтобы перейти непосредственно к записи таблицы, которая содержит соответствующее значение.Однако любая реализация должна иметь дело с возможностью того, что два разных ключа имеют одинаковое хеш-значение (или иным образом отображаются на один и тот же индекс записи с помощью операции по модулю, выполняемой с хеш-значением).Python обрабатывает это с помощью стратегии, называемой «закрытое хеширование»: если соответствующая запись уже взята другим ключом, вычисленная последовательность других возможных записей проверяется, пока не будет найдена пустая.(Таблице не разрешается заполняться почти на 100%, так что эта проверка никогда не занимает необоснованно много времени и гарантированно находит пустую запись.) Реализация get()
следует той же последовательности, пока либонайден правый ключ или найдена пустая запись.
Теперь представьте, что два ключа A
и B
, имеющие коллизию хешей, вставляются в dict в указанном порядке, а затем A
удалено.Если вы реализовали это, установив пустую запись A
, подумайте о том, что произойдет при последующем вызове get(B)
: он сразу найдет эту пустую запись и сообщит, что B
вообще отсутствует!Эта проблема может быть исправлена с помощью специального значения флага, отличного от фактического ключа или пустой записи, которое используется для указания удаленной записи.Когда get()
видит один из них, он знает, что ему нужно продолжать поиск в других возможных местах входа.Когда set()
видит его, он может перезаписать его вставленным ключом (хотя он все равно должен будет сканировать, пока не найдет фактическую пустую запись, чтобы убедиться, что ключ еще не присутствует).