Python 实现字典的自定义键,以便同一类的两个实例匹配

Python 实现字典的自定义键,以便同一类的两个实例匹配,python,python-3.x,dictionary,hash,Python,Python 3.x,Dictionary,Hash,我有两个类的实例,我想将它们解析为字典中的同一个键: class CustomClass(): def __hash__(self): return 2 a = CustomClass() b = CustomClass() dicty = {a : 1} 这里,a和b作为键并不相等: >>> a in dicty True >>> b in dicty False 哈希到底发生了什么;看起来C

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

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。数组
的形状
(8,6)
。我想对这些值进行散列,这样每当将这个对象放入字典时,就会对这些值进行比较。我根据答案把它们做成了一个位数组。我注意到它在那里有一个
\uu\cmp\uu
(感谢
第四个
显示我必须查看那里)。但是,我的类可以更新,所以我只想在实际尝试将np.array放入字典时对其进行散列,而不是在初始化时(因此每当我init时存储可散列位数组,因为np.array可能会被更新,因此散列不再是真正的表示)。我知道每当我更新np.array时,我也可以更新散列值,但我更喜欢只散列一次

\uuuuu散列\uuuuuu
仅确定将值放入哪个存储桶中。在bucket中,python总是调用
\uuuuuuueq\uuu
,以确保它不会返回一个恰好具有相同哈希值但实际上不同的元素,因此您还需要实现自己的
\uuuueq\uu

class CustomClass():
定义散列(自我):
返回2
定义(自身、其他):
返回散列(其他)=散列(自身)
a=自定义类()
b=自定义类()
dicty={a:1}
用口述法打印
用口述法打印b
用口述法打印“a”

\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
仅确定将值放入哪个存储桶中。在bucket中,python总是调用
\uuuuuuueq\uuu
,以确保它不会返回一个恰好具有相同哈希值但实际上不同的元素,因此您还需要实现自己的
\uuuueq\uu

class CustomClass():
定义散列(自我):
返回2
定义(自身、其他):
返回散列(其他)=散列(自身)
a=自定义类()
b=自定义类()
dicty={a:1}
用口述法打印
用口述法打印b
用口述法打印“a”

您应该实现
\uuuuu eq\uuuu
方法,以使对象可散列
。 文档中可散列的
定义:

如果一个对象的散列值在处理过程中从不改变,那么它就是可散列的 它的生存期(它需要一个_hash _;()方法),并且可以 与其他对象相比(它需要一个_eq__()方法)。散列 比较相等的对象必须具有相同的哈希值

哈希性使对象可用作字典键和集合成员,因为这些数据结构在内部使用哈希值


您应该实现
\uuuuueq\uuuu
方法,以使对象
可散列
。 文档中可散列的
定义:

如果一个对象的散列值在处理过程中从不改变,那么它就是可散列的 它的生存期(它需要一个_hash _;()方法),并且可以 与其他对象相比(它需要一个_eq__()方法)。散列 比较相等的对象必须具有相同的哈希值

哈希性使对象可用作字典键和集合成员,因为这些数据结构在内部使用哈希值


您违反了
\uuuuuuuhash\uuuuuuu
\uuucmp\uuuuu
之间的合同。引用

如果类没有定义
\uuu cmp\uuu()
\uuu eq\uuuu()
方法,那么它也不应该定义
\uu hash\uuuuu()
操作;如果它定义了
\uu cmp\uu()
\uu eq\uuu()
而不是
\uuu hash\uuu()
,则其实例将无法在哈希集合中使用。如果类定义了可变对象并实现了
\uuu cmp\uuu()
\uuu eq\uuuu()
方法,那么它不应该实现
\uu hash\uuuu()
,因为可哈希集合实现要求对象的哈希值是不可变的(如果对象的哈希值发生变化,它将位于错误的哈希桶中)

默认情况下,用户定义的类具有
\uuuu cmp\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;使用它们,所有对象都比较不相等(除了它们自己)
x。
返回一个适当的值,使得
x==y
意味着
x是y
hash(x)==hash(y)

在您的例子中,两个对象的哈希值相同,并且在任何哈希实现中都是通用的。因此,Python将正在查找的对象与help
\uuuuu eq\uuu
方法进行比较,发现正在搜索的实际对象与已存储在中的对象不同。这就是为什么dicty中的
b
返回
False

因此,要解决您的问题,还可以定义自定义
\uuuuuuuuuuuuuuuuuuuuuuuuuuueq
函数,如下所示

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
class CustomClass():
定义初始化(自):
self.data=
定义散列(自我):
#基于`数据查找哈希值`
返回散列(self.data)
定义(自身、其他):
返回self.data==other.data
注意:
\uuuuuuuuuuuuuuuuuuuu散列值对于给定对象应始终相同。因此,请确保
数据
class CustomClass: 
    def __hash__(self):
        return 2
    def __eq__(self, other):
        return type(self) is type(other) and type(self) is CustomClass