Почему я не могу вызвать hash() для явно хэшируемого метода неустрашимого экземпляра?

Допустим, у меня есть словарь:

>>> d = {}

У него есть метод clear():

>>> d.clear
<built-in method clear of dict object at 0x7f209051c988>

... который имеет __hash__ атрибут:

>>> d.clear.__hash__
<method-wrapper '__hash__' of builtin_function_or_method object at 0x7f2090456288>

... который вызывается:

>>> callable(d.clear.__hash__)
True

Так почему я не могу хэшировать это?

>>> hash(d.clear)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'

Примечание: я знаю, что dict объекты не подлежат уничтожению - мне любопытно, почему это ограничение распространяется на их методы, хотя, как отмечалось выше, они, по-видимому, утверждают иное?

2 ответа

Решение

Это связанный метод, а связанные методы имеют ссылку на selfНапример, словарь. Это делает метод не хэшируемым.

Вы можете хешировать несвязанные dict.clear метод:

>>> d = {}
>>> d.clear.__self__
{}
>>> d.clear.__self__ is d
True
>>> hash(d.clear)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>> hash(dict.clear)
-9223372036586189204

Методы в экземплярах, которые являются хэшируемыми, сами будут хэшируемыми, поэтому тип объекта для встроенных связанных методов реализует __hash__ метод, но поднимает TypeError когда __self__ атрибут не является хэш Это согласуется с object.__hash__ методическая документация; если вы можете установить его None или не реализовывать его вообще, тогда это предпочтительнее, но для тех случаев, когда хеш-память известна только во время выполнения, поднимая TypeError это единственный доступный вариант.

Мартейн прав, как он часто бывает. Если у тебя есть dict подкласс, который реализует __hash__ метод, даже связанные методы становятся хэш

class MyHashableDict(dict):
    def __hash__(self):
        return 42

x = MyHashableDict()
print(x, hash(x), hash(x.clear))

y = {}
print(y, hash(y.clear))

Выход:

{} 42 287254
Traceback (most recent call last):
  File "y.py", line 9, in <module>
    print(hash(y.clear))
TypeError: unhashable type: 'dict'
Другие вопросы по тегам