移植一个功能,我的程序的Python 3.1中,叉,当我有一个奇怪的错误。 我把范围缩小到以下假设:
相反到Python 2.x中,在Python 3.X如果对象具有__eq__
方法是自动unhashable。
这是真的?
下面是在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
指向几个对象,在过去的某个时间点给出了每个他们的泡菜转储的价值。 当现有的对象被选中的,变更跟踪表示,其新的泡菜是否等同于它的旧人,所以说,在此期间对象是否已经改变。 问题是,现在我甚至不能检查,如果给定对象是在图书馆,因为它使得提高对对象是unhashable例外。 (因为它有一个__eq__
方法。)我如何解决此问题?
是的,如果你定义__eq__
,默认__hash__
(即,散列对象在内存中的地址)消失。 这是重要的,因为哈希需要与平等一致的:等于对象需要哈希相同。
解决方法很简单:只要定义__hash__
与限定沿着__eq__
。
这一段从http://docs.python.org/3.1/reference/datamodel.html#object。 哈希
如果覆盖了一个类__eq__()
需要保留的实施__hash__()
从父类,解释器必须明确通过设置被告知此__hash__ = <ParentClass>.__hash__
。 否则的继承__hash__()
将被阻塞,就像__hash__
已明确设置为无。
Check the Python 3 manual on object.__hash__
:
If a class does not define an __eq__()
method it should not define a __hash__()
operation either; if it defines __eq__()
but not __hash__()
, its instances will not be usable as items in hashable collections.
Emphasis is mine.
If you want to be lazy, it sounds like you can just define __hash__(self)
to return id(self)
:
User-defined classes have __eq__()
and __hash__()
methods by default; with them, all objects compare unequal (except with themselves) and x.__hash__()
returns id(x)
.
我不是专家的Python,但不会是有意义的是,当你定义EQ-方法,你也必须定义一个散列法以及(其计算对象的哈希值),否则,散列机制不知道,如果它击中同一个对象,或只用相同的哈希值不同的对象。 其实,这是周围的其他方法,它很可能为这样的考虑你相等的对象不同的计算哈希值__eq__
方法。
我不知道那是什么散列函数,虽然叫, __hash__
吧? :)