实现dictionary的自定义键,以便相同类的2个实例匹配

2024-06-01 02:03:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个类实例,我想将它们解析为字典中的同一个键:

class CustomClass(): 
    def __hash__(self):
        return 2

a = CustomClass()        
b = CustomClass()        

dicty = {a : 1}

这里,a和b不等于键:

^{pr2}$

hash到底发生了什么;CustomClass的第二个实例似乎应该与哈希匹配?为什么这些哈希值不匹配?在

我刚刚发现实际的类是被散列的。那么如何为一个类添加一个自定义字典键(即当我试图将一个类用作字典的键时,应该如何存储它以便a和b匹配)?在

请注意,在这种情况下,我不关心在字典中保留一个指向原始对象的链接,我可以处理一些不可用的键对象;只是它们解决问题的方法相同而已。在

编辑:

也许需要一些关于我想解决的实际案件的建议。在

我有一些类包含形状为(8,6)的布尔np.arrays。我想散列这些值,这样每当这个对象被放入字典时,就会对这些值进行比较。我根据this的答案把它们做成了一个位数组。我注意到它有一个__cmp__(谢谢thefourtheye让我看那里)。但是,我的类可以更新,所以我只想散列np.数组当我实际尝试将它放入字典中,而不是在初始化时(因此每当我init时存储散列位数组,因为np.数组可能会被更新,因此哈希不再是真正的表示形式)。我知道每当我更新np.数组,我也可以更新哈希值,但我宁愿只哈希一次!在


Tags: 对象实例selfreturn字典defnp情况
3条回答

__hash__只决定将值放入哪个bucket。在bucket中,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

你违反了__hash____cmp__和{}之间的合同。引用^{} 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返回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在最初分配后从未更改过。否则,您将永远无法从字典中获取对象,因为hashdata值将不同,如果它在稍后的时间点发生变化。在

问题是哈希函数会导致冲突——不同的对象可以产生相同的哈希值。因此,最终检查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

相关问题 更多 >