Какова логика порядка хеш-функций Python?

Как известно, некоторые структуры данных Python используют хэш-таблицы для хранения таких элементов, как set или dictionary. Таким образом, в этих объектах нет порядка. Но кажется, что для некоторых последовательностей чисел это неверно.

Например, рассмотрим следующие примеры:

>>> set([7,2,5,3,6])
set([2, 3, 5, 6, 7])

>>> set([4,5,3,0,1,2])
set([0, 1, 2, 3, 4, 5])

Но он не сортируется, если мы сделаем небольшое изменение:

>>> set([8,2,5,3,6])
set([8, 2, 3, 5, 6])

Итак, вопрос: как работает хэш-функция Python над целыми последовательностями?

Ответ 1

Хотя в SO есть много вопросов о hash и его порядке, но ни один из них не объясняет алгоритм хэш-функции.

Итак, все, что вам нужно, это знать, как python вычисляет индексы в хэш-таблице.

Если вы просмотрите файл hashtable.c в исходном коде CPython, вы увидите следующие строки в функции _Py_hashtable_set, которая показывает way python вычисляет индекс ключей хеш-таблицы:

key_hash = ht->hash_func(key);
index = key_hash & (ht->num_buckets - 1);

Так как хэш-значение целых чисел является самим целым * (кроме -1), индекс основывается на числе и длине вашей структуры данных (ht->num_buckets - 1) и вычисляется с помощью Побитового и между (ht->num_buckets - 1) и номер.

Теперь рассмотрим следующий пример с set, который использует хеш-таблицу:

>>> set([0,1919,2000,3,45,33,333,5])
set([0, 33, 3, 5, 45, 333, 2000, 1919])

Для числа 33 имеем:

33 & (ht->num_buckets - 1) = 1

На самом деле это:

'0b100001' & '0b111'= '0b1' # 1 the index of 33

Обратите внимание, что в этом случае (ht->num_buckets - 1) есть 8-1=7 или 0b111.

И для 1919:

'0b11101111111' & '0b111' = '0b111' # 7 the index of 1919

И для 333:

'0b101001101' & '0b111' = '0b101' # 5 the index of 333

И так же, как и в предыдущих примерах:

>>> set([8,2,5,3,6])
set([8, 2, 3, 5, 6])

'0b1000' & '0b100'='0b0' # for 8
'0b110' & '0b100'='0b100' # for 8

<суб > * Хэш-функция для класса int:

class int:
    def __hash__(self):
        value = self
        if value == -1:
            value = -2
        return value

суб >