为什么我不能在不可散列实例的明显可散列方法上调用 hash()?

Why can't I call hash() on an apparently hashable method of an unhashable instance?

假设我有一本字典:

>>> 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 对象是不可散列的——我很好奇为什么这个限制会扩展到他们的方法,尽管如上所述,他们似乎另有说法?

它是一个绑定方法,绑定方法有对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 是唯一可用的选项。

Martijn 是对的,他经常是这样。如果你有一个 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'