Есть ли сценарий переопределения __hash__? - PullRequest
1 голос
/ 25 июня 2019

В Python3 любой класс будет иметь значение по умолчанию __hash__, которое вычисляет хэш на основе переменных-членов.Я могу установить его (явным или неявным образом) в None, чтобы сделать класс не хэшируемым, что, безусловно, имеет некоторые варианты использования.

Но есть ли причины для переопределения __hash__?

Я не смог его найти.

1 Ответ

2 голосов
/ 25 июня 2019

Да! Каждый раз, когда вы переопределяете __eq__, а также хотите иметь возможность использовать объект в качестве ключа в наборе или дикте. Это особенно часто встречается в типах значений или в случаях, когда ваши объекты представляют сущности реального мира.

__hash__ вообще не хэширует переменные-члены. Для объекта без __hash__ или __eq__ он возвращает некоторое значение на основе своего внутреннего указателя. Если __eq__ определено , то вызов метода вызовет TypeError.work

Рассмотрим простой случай, когда поведение по умолчанию __eq__ и __hash__ невелико:

import getpass

class User:
    def __init__(self, name):
        self.name = name

def currentUser():
   return User(getpass.getuser())

me = currentUser()

passwords = {}
passwords[me] = "sw0rdfish";

Это странное поведение: me == currentUser() ложно, а passwords[currentUser()] выдает KeyError. Поэтому, чтобы попытаться это исправить, мы определяем __eq__:

def __eq__(self, other): 
    return self.name == other.name

Теперь me == currentUser() имеет значение true, но при попытке назначить пароль выдается TypeError: unhashable type: 'User'. Теперь мы добрались до точки, где мы хотим переопределить __hash__:

def __hash__(self):
    return hash(self.name)

И теперь он ведет себя так, как будто вы ожидаете, что любой другой такой объект будет работать, когда вы используете его в качестве ключа.

...