我有两个类的实例,我想解析为字典中的相同键:
class CustomClass():
def __hash__(self):
return 2
a = CustomClass()
b = CustomClass()
dicty = {a : 1}
这里,a和b不等于键:
>>> a in dicty
True
>>> b in dicty
False
哈希到底发生了什么?看起来CustomClass的第二个实例应该与散列相匹配?这些哈希值与之不匹配的是什么?
我刚才发现实际的课程正在被散列。那么如何为类添加自定义词典键(即当我尝试使用类作为词典的键时,应该如何存储以使a和b匹配)?
请注意,在这种情况下,我不关心保持字典中原始对象的链接,我可以使用一些不可用的密钥对象;只要重要的是他们解决问题。
编辑:
或许需要就我想要解决的实际案例提出一些建议。
我的类包含形状np.arrays
的布尔(8,6)
。我想对这些进行散列,这样无论何时将此对象放入字典中,都会对这些值进行比较。根据{{3}}回答,我从他们身上做了一个小小的问题。我注意到它有一个__cmp__
(感谢thefourtheye
显示我必须看那里)。但是,我的课程可以更新,所以我只想在我实际尝试将它放入字典中而不是在启动时(或者因此在每次我存储可存储的比特阵列时)对np.array进行哈希处理。 init ,因为np.array可能会被更新,因此哈希不再是真实的表示形式。我知道每当我更新np.array时,我也可以更新散列值,但我更喜欢只散列一次!
答案 0 :(得分:5)
您违反了__hash__
,__cmp__
和__eq__
之间的合同。引用__hash__
documentation,
如果某个类未定义
__cmp__()
或__eq__()
方法,则不应定义__hash__()
操作;如果它定义__cmp__()
或__eq__()
但不定义__hash__()
,则其实例将无法在散列集合中使用。如果一个类定义了可变对象并实现了__cmp__()
或__eq__()
方法,那么它不应该实现__hash__()
,因为hashable collection实现要求对象的哈希值是不可变的(如果对象的哈希值)更改,它将在错误的哈希桶中。)默认情况下,用户定义的类具有
__cmp__()
和__hash__()
方法;与他们一起,所有对象比较不相等(除了他们自己)和x.__hash__()
返回一个适当的值,x == y
同时暗示x is y
和hash(x) == hash(y)
。
在您的情况下,两个对象的哈希值相同,hash Collision在任何哈希实现中都很常见。因此,Python将正在查找的对象与帮助__eq__
方法进行比较,并发现被搜索的实际对象与已存储的对象不同。这就是为什么b in dicty
返回{{1 }}
因此,要解决您的问题,请定义自定义False
功能,如此
__eq__
注意:对于给定对象, class CustomClass():
def __init__(self):
self.data = <something>
def __hash__(self):
# Find hash value based on the `data`
return hash(self.data)
def __eq__(self, other):
return self.data == other.data
值应始终相同。因此,请确保在最初分配后__hash__
永远不会更改。否则,您永远无法从字典中获取对象,因为data
hash
的值将会有所不同,如果它在稍后的时间点发生变化。
答案 1 :(得分:1)
__hash__
只确定将值放入哪个存储桶。在存储桶中,python始终调用__eq__
以确保它不会返回恰好具有相同哈希值的元素,但实际上它不同,因此您需要实现自己的__eq__
同样。
class CustomClass():
def __hash__(self):
return 2
def __eq__(self, other):
return hash(other) == hash(self)
a = CustomClass()
b = CustomClass()
dicty = {a : 1}
print a in dicty
print b in dicty
print "a" in dicty
答案 2 :(得分:1)
您应该实施__eq__
方法来制作对象hashable
。
来自doc的hashable
的定义:
如果对象具有在此期间永远不会更改的哈希值,则该对象是可清除的 它的生命周期(它需要一个__hash __()方法),并且可以 与其他对象相比(它需要一个__eq __()方法)。可哈希 比较相等的对象必须具有相同的哈希值。
Hashability使对象可用作字典键和set成员,因为这些数据结构在内部使用哈希值。
答案 3 :(得分:1)
问题是哈希函数可能导致冲突 - 不同的对象可以产生相同的哈希值。因此,最终检查以确定对象是否存在于dict中仍然使用相等比较(即x == y
)来完成。哈希值首先用于快速查找相关对象。
如果您想要您描述的行为,那么您也必须覆盖__eq__
。
例如
class CustomClass:
def __hash__(self):
return 2
def __eq__(self, other):
return type(self) is type(other) and type(self) is CustomClass