当我将一个特性移植到我的程序的Python3.1fork时,我遇到了一个奇怪的bug。我把它的范围缩小到以下假设:
与Python2.x不同的是,在Python3.x中,如果一个对象有一个__eq__
方法,那么它就是自动不可散列的。
这是真的吗?
以下是Python 3.1中发生的事情:
>>> class O(object):
... def __eq__(self, other):
... return 'whatever'
...
>>> o = O()
>>> d = {o: 0}
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
d = {o: 0}
TypeError: unhashable type: 'O'
接下来的问题是,我如何解决我的个人问题?我有一个对象ChangeTracker
,它存储一个指向多个对象的WeakKeyDictionary
,给出每个对象在过去某个时间点的酸洗转储的值。无论何时签入现有的对象,变更跟踪器都会判断其新的pickle是否与旧的相同,因此会指出该对象在此期间是否已更改。问题是,现在我甚至不能检查给定的对象是否在库中,因为它会引发一个关于该对象不可散列的异常。(因为它有一个__eq__
方法。)我该如何解决这个问题呢?
发布于 2009-10-23 01:51:11
是的,如果你定义了__eq__
,默认的__hash__
(也就是散列内存中对象的地址)就消失了。这一点很重要,因为散列需要与相等一致:相等的对象需要散列相同的内容。
解决方案很简单:只需在定义__eq__
的同时定义__hash__
。
发布于 2009-10-23 01:49:38
我不是python专家,但是当你定义一个eq-method时,你也必须定义一个散列方法(它计算一个对象的散列值),这不是很有意义吗?否则,散列机制将不知道它是命中相同的对象,还是使用相同的散列值的不同对象。实际上,情况正好相反,它可能会为__eq__
方法认为相等的对象计算不同的散列值。
我不知道这个散列函数叫什么,也许是__hash__
?:)
https://stackoverflow.com/questions/1608842
复制相似问题