Почему python3 выдает одно и то же значение хеш-функции для -1 и -2?

Я пробовал python3 встроенный метод hash() для произвольных значений, затем диапазонов и увидел кое-что забавное:

>>> [hash(i) for i in range(-20,20)]
[-20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

Хэш-значение, полученное для целых чисел, обычно является самим целым числом, за исключением -1, которое по какой-то причине равно -2, как и значение -2.

Мой интерпретатор Python3:

Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux

Это можно воспроизвести и в другом месте, например, в repl.it, который произвел:

Python 3.6.1 (default, Dec 2015, 13:05:11)
[GCC 4.8.2] on linux
hash(1)
=> 1
[hash(i) for i in range(-20,20)]
=> [-20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]   

<iframe height="400px" width="100%" src="https://repl.it/@aalok_sathe/FairCornflowerblueLadybug?lite=true" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe>

Я понимаю, что хеширование может привести к коллизиям, и если это вообще случай коллизии, я не ожидал, что это произойдет в таком маленьком масштабе. Я ищу что-нибудь, что могло бы помочь объяснить это поведение, и любые советы о том, какие альтернативы/обходные пути можно использовать, когда мне действительно нужно использовать это в программе (тот, о котором я могу думать, это преобразование целых чисел в строки, а затем хеширование, но это не позволит разным типам иметь разные хеш-значения). Помимо специфики приложения, я просто озадачен этим, поэтому любой указатель поможет.


person axolotl    schedule 09.02.2018    source источник
comment
Зачем вам нужен обходной путь? Словари Python автоматически обрабатывают разрешение коллизий, как и любая другая реализация хэш-таблицы общего назначения.   -  person user2357112 supports Monica    schedule 09.02.2018
comment
Хэши предназначены и могут быть равны хешу другого объекта. Если вам для чего-то нужны уникальные хэши, вы делаете это неправильно.   -  person poke    schedule 09.02.2018
comment
@poke Я понимаю это, но разве нельзя ожидать, что small целые числа будут иметь различимые хэш-значения, особенно если они кажутся шаблонными?   -  person axolotl    schedule 09.02.2018
comment
Что ж, схема очень проста: все целые числа хешируются сами с собой, кроме -1. И нет, как правило, у вас не должно быть никаких ожиданий относительно хеш-значений. Это деталь реализации, на которую не следует опираться.   -  person poke    schedule 09.02.2018