Для работы __hash__
метод должен удовлетворять следующему требованию:
Так x * y, что x == y
, затем hash(x) == hash(y)
.
В вашем случае ваш класс не реализует __eq__
, что означает, что x == y
тогда и только тогда, когда id(x) == id(y)
, и, следовательно, ваша хеш-реализация удовлетворяет вышеуказанному свойству.
Обратите внимание, однако, что если вы делаете внедрите __eq__
, то эта реализация, скорее всего, завершится неудачей.
Кроме того: существует разница между наличием «действительного» * 1018 * и наличием хорошего хеша. Например, следующее является допустимым __hash__
определением для любого класса:
def __hash__(self):
return 1
Хороший хеш должен пытаться распределить объекты равномерно, чтобы избежать коллизий в максимально возможной степени. Обычно это требует более сложного определения.
Я бы не пытался придумывать формулы и полагаться на встроенную в Python функцию hash
.
Например, если в вашем классе есть поля a
, b
и c
, я бы использовал что-то вроде этого __hash__
:
def __hash__(self):
return hash((self.a, self.b, self.c))
Определение hash
для кортежей должно быть достаточно хорошим для среднего случая.
Наконец: вы не должны определять __hash__
в изменчивых классах (в полях, используемых для равенства). Это потому, что изменение экземпляров изменит их хэш, и это сломает вещи.