Ответ абсолютно не удивителен: на самом деле
In [1]: -5768830964305142685L & 0xffffffff
Out[1]: 1934711907L
поэтому, если вы хотите получить надежные ответы на строки ASCII , просто получите младшие 32 бита как uint
. Хеш-функция для строк безопасна для 32-бит и почти переносима.
С другой стороны, вы вообще не можете полагаться на получение hash()
любого объекта, для которого вы явно не определили метод __hash__
как инвариантный.
Над строками ASCII это работает только потому, что хеш рассчитывается для отдельных символов, образующих строку, как показано ниже:
class string:
def __hash__(self):
if not self:
return 0 # empty
value = ord(self[0]) << 7
for char in self:
value = c_mul(1000003, value) ^ ord(char)
value = value ^ len(self)
if value == -1:
value = -2
return value
где функция c_mul
- это "циклическое" умножение (без переполнения), как в C.