为字典实现自定义键,以便相同 class 的 2 个实例匹配
Implement custom keys for dictionary so that 2 instances of same class match
我有 2 个 classes 实例,我想将其解析为字典中的同一个键:
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 的第二个实例应该匹配散列?这些哈希值不匹配是怎么回事?
我刚刚发现真正的 class 是被散列的东西。那么如何为 class 添加自定义字典键(即当我尝试使用 class 作为字典的键时,应该如何存储它以便 a 和 b 匹配)?
请注意,在这种情况下,我不关心将 link 保留到字典中的原始对象,我可以使用一些不可用的键对象;重要的是他们决心相同。
编辑:
也许需要一些关于我想解决的实际案例的建议。
我有 classes 包含形状 (8,6)
的布尔值 np.arrays
。我想对这些进行哈希处理,以便每当将此对象放入字典时,都会对这些值进行比较。我根据 this 的回答用它们做了一个位数组。我注意到那里有一个 __cmp__
(感谢 thefourtheye
让我看到那里)。但是,我的 class 可以更新,所以我只想在我实际尝试将它放入字典时散列 np.array,而不是在启动时散列(从而存储可散列的位数组每当我 init 时,因为 np.array 可能会更新,这样散列就不再是真实的表示了)。我知道每当我更新 np.array 时,我也可以更新散列值,但我宁愿只散列一次!
__hash__
只是确定将值放入哪个桶中。在桶内 python 总是调用 __eq__
以确保它不会 return 一个元素恰好具有相同的哈希值,但实际上是不同的,所以你需要也实施您自己的 __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
您应该实施 __eq__
方法来使您的对象 hashable
。
来自文档的 hashable
的定义:
An object is hashable if it has a hash value which never changes during
its lifetime (it needs a __hash__() method), and can be
compared to other objects (it needs an __eq__() method). Hashable
objects which compare equal must have the same hash value.
Hashability makes an object usable as a dictionary key and a set member, because these data structures use the hash value internally.
您违反了 __hash__
、__cmp__
和 __eq__
之间的契约。引用 __hash__
documentation,
If a class does not define a __cmp__()
or __eq__()
method it should not define a __hash__()
operation either; if it defines __cmp__()
or __eq__()
but not __hash__()
, its instances will not be usable in hashed collections. If a class defines mutable objects and implements a __cmp__()
or __eq__()
method, it should not implement __hash__()
, since hashable collection implementations require that a object’s hash value is immutable (if the object’s hash value changes, it will be in the wrong hash bucket).
User-defined classes have __cmp__()
and __hash__()
methods by default; with them, all objects compare unequal (except with themselves) and x.__hash__()
returns an appropriate value such that x == y
implies both that x is y
and hash(x) == hash(y)
.
在您的例子中,两个对象的散列值相同,并且 hash Collision 在任何散列实现中都很常见。所以,Python用help__eq__
方法对比查找的对象,发现实际查找的对象和已经存入的对象不一样,所以b in dicty
returns 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
的值 data
会有所不同,如果它在稍后的时间点发生变化。
问题在于散列函数可能会导致冲突——不同的对象可能会产生相同的散列值。因此,最终检查对象是否存在于字典中仍然使用相等比较(即 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
我有 2 个 classes 实例,我想将其解析为字典中的同一个键:
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 的第二个实例应该匹配散列?这些哈希值不匹配是怎么回事?
我刚刚发现真正的 class 是被散列的东西。那么如何为 class 添加自定义字典键(即当我尝试使用 class 作为字典的键时,应该如何存储它以便 a 和 b 匹配)?
请注意,在这种情况下,我不关心将 link 保留到字典中的原始对象,我可以使用一些不可用的键对象;重要的是他们决心相同。
编辑:
也许需要一些关于我想解决的实际案例的建议。
我有 classes 包含形状 (8,6)
的布尔值 np.arrays
。我想对这些进行哈希处理,以便每当将此对象放入字典时,都会对这些值进行比较。我根据 this 的回答用它们做了一个位数组。我注意到那里有一个 __cmp__
(感谢 thefourtheye
让我看到那里)。但是,我的 class 可以更新,所以我只想在我实际尝试将它放入字典时散列 np.array,而不是在启动时散列(从而存储可散列的位数组每当我 init 时,因为 np.array 可能会更新,这样散列就不再是真实的表示了)。我知道每当我更新 np.array 时,我也可以更新散列值,但我宁愿只散列一次!
__hash__
只是确定将值放入哪个桶中。在桶内 python 总是调用 __eq__
以确保它不会 return 一个元素恰好具有相同的哈希值,但实际上是不同的,所以你需要也实施您自己的 __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
您应该实施 __eq__
方法来使您的对象 hashable
。
来自文档的 hashable
的定义:
An object is hashable if it has a hash value which never changes during its lifetime (it needs a __hash__() method), and can be compared to other objects (it needs an __eq__() method). Hashable objects which compare equal must have the same hash value.
Hashability makes an object usable as a dictionary key and a set member, because these data structures use the hash value internally.
您违反了 __hash__
、__cmp__
和 __eq__
之间的契约。引用 __hash__
documentation,
If a class does not define a
__cmp__()
or__eq__()
method it should not define a__hash__()
operation either; if it defines__cmp__()
or__eq__()
but not__hash__()
, its instances will not be usable in hashed collections. If a class defines mutable objects and implements a__cmp__()
or__eq__()
method, it should not implement__hash__()
, since hashable collection implementations require that a object’s hash value is immutable (if the object’s hash value changes, it will be in the wrong hash bucket).User-defined classes have
__cmp__()
and__hash__()
methods by default; with them, all objects compare unequal (except with themselves) andx.__hash__()
returns an appropriate value such thatx == y
implies both thatx is y
andhash(x) == hash(y)
.
在您的例子中,两个对象的散列值相同,并且 hash Collision 在任何散列实现中都很常见。所以,Python用help__eq__
方法对比查找的对象,发现实际查找的对象和已经存入的对象不一样,所以b in dicty
returns 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
的值 data
会有所不同,如果它在稍后的时间点发生变化。
问题在于散列函数可能会导致冲突——不同的对象可能会产生相同的散列值。因此,最终检查对象是否存在于字典中仍然使用相等比较(即 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