为什么我不能在一个看似可哈希的方法上调用hash(),而该方法属于一个不可哈希实例?

25

假设我有一个字典:

>>> 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个回答

33

这是一个绑定方法,绑定方法有一个指向 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__方法,但当__self__属性不可哈希时,会引发TypeError异常。这与object.__hash__方法文档一致;如果可以将其设置为None或根本不实现它,则更好,但对于这些仅在运行时已知可哈希性的情况,引发TypeError是唯一可用的选择。


11

Martijn是正确的,就像他通常所做的那样。如果你有一个实现__hash__方法的dict子类,即使绑定方法也变得可哈希。

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'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接