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

4

2 回答 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__引发。这与方法文档一致;如果您可以将其设置为或根本不实现它,那么这是可取的,但对于仅在运行时才知道哈希性的情况,提高 a是唯一可用的选项。TypeError__self__object.__hash__NoneTypeError

于 2015-03-24T17:27:43.843 回答
11

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'
于 2015-03-24T20:19:32.337 回答