Какие значения могут быть ключами словаря?
Документация гласит, что ключами могут быть только неизменяемые типы данных. Почему в данном случае не возникает ошибка?
class Test:
pass
t = Test()
print({t: 1})
Документация гласит, что ключами могут быть только неизменяемые типы данных. Почему в данном случае не возникает ошибка?
class Test:
pass
t = Test()
print({t: 1})
Попробую ответить, т.к. вопрос интересный и сам не знал почему.
Коротко: причина в наличии магическом методе __hash__
Если мы используем словарь как ключ:
t = dict()
d = {t: 1}
То получаем ошибку:
TypeError: unhashable type: 'dict'
Но, вообще-то, эту же ошибку получим, если попробуем получить хеш:
t = dict()
print(hash(t))
У не хешируемых типов, магический метод __hash__
отсутствует:
t = dict()
print(t.__hash__)
# None
Вот так выглядит наличие этого метода:
print(Test.__hash__)
# <slot wrapper '__hash__' of 'object' objects>
t = Test()
print(t.__hash__)
# <method-wrapper '__hash__' of Test object at ...
Мы это легко проверим на нашем классе Test
:
class Test:
__hash__ = None
t = Test()
d = {t: 1}
Знакомая ошибка:
TypeError: unhashable type: 'Test'
ℹ️ Выходит, что у классов, по-умолчанию, есть метод __hash__
, поэтому их можно использовать в ключах словаря и в других местах (типа множеств), реализованных через хеши
Кст, по-умолчанию, хеш высчитывается из id
объекта деленного на 16.
Тут будет одинаковый результат:
class Test:
pass
t = Test()
print(hash(t))
print(hash(id(t) // 16))