#python #hash
#питон #хэш #python
Вопрос:
На моей машине hash(None)
возвращает значение:
>>> hash(None)
-2138947203
Просто из любопытства, как вычисляется это хэш-значение? Не похоже, что это значение основано на None
‘s id
, поскольку оно будет таким же, если я перезапущу интерпретатор Python.
Комментарии:
1. Не совпадает ли идентификатор (нет) при перезапуске интерпретатора Python?
2. на самом деле оба
id
иhash
равны при перезапуске Python. Я бы предположил, что это просто какая-то позиция внутри двоичного файла Python.3. Интересные моменты. Я даже не подумал это проверить!
Ответ №1:
Он основан на None id
, но None является одним из нескольких объектов Python, которые определены как глобальные переменные C, поэтому его адрес (обычно) не меняется между запусками Python. Другими такими объектами являются True
and False
(но они хэшируются как целые числа) или встроенные классы, такие как object
and tuple
.
Однако адрес (и хэш) различаются в разных сборках CPython. В моей системе hash(None)
выдает 539708.
Комментарии:
1. Излишне говорить, что это деталь реализации CPython, поэтому вам не следует полагаться на нее.
2. Просто из любопытства, как можно на это полагаться?
3. @ChrisW., нет, это не будет проблемой, поскольку hash() этого объекта все равно останется неизменным до тех пор, пока объект живет (поскольку вы не можете перемещать живые объекты в разные сеансы Python).
4. @ChrisW. ДА. Это также произойдет, например
True
, с любым объектом, который не переопределяется__hash__
. И сPYTHONHASHSEED
установленным значениемrandom
(рекомендуется для веб-серверов) для строк.5. Обратите внимание, что адрес может меняться между запусками одного и того же двоичного файла pythong, если в вашей операционной системе включена рандомизация адресного пространства.
Ответ №2:
Он основан на адресе None
в памяти, как указано в определении типа.
Комментарии:
1. ссылка мертва, вы должны были включить соответствующую часть содержимого ссылки в свой ответ
Ответ №3:
Как None
и объект, я написал функцию object_hash
для вычисления хэша объекта:
import sys
import struct
def int_overflow(value):
""" simulate integer overflow """
m = sys.maxint 1
return (value m) % (m * 2) - m
def object_hash(value):
res = id(value)
sizeof_void_p = struct.calcsize('P')
res = int_overflow((res >> 4) | (res << (8 * sizeof_void_p - 4)))
if res == -1:
res = -2
return res
Результирующие хэши равны:
>>> hash(None)
492116
>>> object_hash(None)
492116L
Ответ №4:
Начиная с Python v3.12.0a4 и CPython PR #99541, значение хэша None
теперь является постоянным.