Подтвердить что ты не робот

Почему -1 и -2 оба хеша до -2 в CPython?

Возможный дубликат:
Когда вычисляется хэш-объект python и почему хэш -1 отличается?

Почему -1 и -2 оба хеша одинакового числа, если Python?

Как они это делают, как Python сообщает эти два числа друг от друга?

>>> -1 is -2
False
>>> hash(-1) is hash(-2)
True
>>> hash(-1)
-2
>>> hash(-2)
-2
4b9b3361

Ответ 1

Обновление - я думаю, что теперь это вики, не стесняйтесь добавлять дополнительную информацию.

-1 является зарезервированным значением на уровне C (CPython - см. комментарии DSM об этом "как ожидалось" в ironpython и pypy).

См. этот ответ Quora:

Если вы пишете тип в модуле расширения C и предоставляете tp_hash метод, вы должны избегать -1 - если вы возвращаете -1, Python будет считать вы хотели выбросить ошибку.

Если вы пишете класс в чистом Python и предоставляете метод __hash__к счастью, такого требования нет. Но это потому, что код C который вызывает ваш метод __hash__, делает это для вас - если ваш __hash__ возвращает -1, то hash(), примененный к вашему объекту, фактически вернет -2.

который действительно просто переупаковывает информацию из effbot:

Значение хэша -1 зарезервировано (его используется для отметки ошибок в C реализация). Если хэш-алгоритм генерирует это значение, мы просто вместо этого используйте -2. ​​

Кроме того, из agf в комментариях (где люди запрашивают дополнительную информацию), источник.


Как они это делают, как Python сообщает эти два числа друг от друга?

Поскольку все хеш-функции отображают большое пространство ввода в меньшее входное пространство, всегда ожидаются столкновения, независимо от того, насколько хороша хэш-функция. Например, подумайте о хеширующих строках. Если хэш-коды являются 32-битными целыми числами, у вас есть 2 ^ 32 (чуть более 4 миллиардов) хэш-кодов. Если вы считаете все строки ASCII длиной 6, у вас есть (2 ^ 7) ^ 6 (чуть менее 4,4 трлн.) Разных предметов в вашем пространстве ввода. Только с этим набором вы гарантированно будете иметь много коллизий, независимо от того, насколько вы хороши. Добавьте символы Unicode и строки неограниченной длины к этому!

Поэтому хеш-код только намекает на местоположение объекта, для проверки ключей-кандидатов следует тест равенства. Чтобы реализовать тест членства в наборе хэш-таблиц, хеш-код дает вам "ведро", в котором нужно искать значение. Однако все элементы с одинаковым хэш-кодом находятся в ведре. Для этого вам также нужен тест равенства, чтобы различать всех кандидатов в ведре.

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


В самом деле, сегодня релиз Python адресован именно этому, с патчем безопасности, который решает проблему эффективности, когда это (одинаковые значения хэша, но в массовом масштабе) используется как атака отказа в обслуживании - http://mail.python.org/pipermail/python-list/2012-April/1290792.html