定义`__eq__`的types是不可以的?
将function移植到我的程序的Python 3.1分支时,出现了一个奇怪的错误。 我缩小到以下假设:
与Python 2.x相反,在Python 3.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 dump的值。 每当一个已经存在的对象被检入时,变更跟踪器就会说新的pickle是否与旧的pickle是一样的,因此说明对象是否已经改变了。 问题是,现在我甚至不能检查给定的对象是否在库中,因为它会引发一个关于不可对象的exception。 (因为它有一个__eq__
方法。)我该如何解决这个问题?
是的,如果你定义了__eq__
,默认的__hash__
(即散列在内存中的对象的地址)就会消失。 这很重要,因为散列需要与等式一致:相同的对象需要散列相同。
解决方法很简单:只需定义__hash__
以及定义__eq__
。
本段来自http://docs.python.org/3.1/reference/datamodel.html#object。; 哈希
如果覆盖
__eq__()
需要保留父类的__hash__()
的实现,则必须通过设置__hash__ = <ParentClass>.__hash__
明确告诉解释器。 否则,__hash__()
的inheritance将被阻塞,就像__hash__
被显式设置为None一样。
检查object.__hash__
的Python 3手册object.__hash__
:
如果一个类没有定义
__eq__()
方法,它不应该定义一个__hash__()
操作。 如果它定义__eq__()
而不是__hash__()
,则它的实例将不可用作可哈希集合中的项目。
重点是我的。
如果你想懒惰,听起来就像你可以定义__hash__(self)
来返回id(self)
:
用户定义的类默认具有
__eq__()
和__hash__()
方法; 与他们,所有的对象比较不平等(除了自己)和x.__hash__()
返回id(x)
。
我不是Python专家,但是当你定义一个eq-method的时候,你也必须定义一个hash-method(它计算一个对象的hash值),这样做没有意义。否则,哈希机制不知道它是否碰到了同一个对象,或者是一个具有相同散列值的不同对象。 实际上,这是相反的,它最终可能__eq__
算出不同的散列值,这些散列值被你的__eq__
方法认为是相等的。
我不知道是什么哈希函数被称为虽然, __hash__
也许? 🙂