我想写一个可以用作可散列集合中的键的类(例如在dict
中)。我知道用户类默认是可以使用的,但使用id(self)
在这里是错误的。
我的班级将tuple
作为成员变量。从tuple
派生似乎不是一个选项,因为在我的构造函数中,我没有得到与tuple
构造函数相同的参数。但也许这不是一个限制?
我需要的基本上是tuple
的散列,就像一个真正的元组给它的方式。
hash(self.member_tuple)
就是这么做的。
这里的想法是两个元组可以相等,而id
不等。
如果我按如下方式实施__cmp__()
:
def __cmp__(self, other):
return cmp(self, other)
这会自动依靠hash(self)
进行比较吗? ......或者我应该按如下方式实施它:
def __cmp__(self, other):
return cmp(self.member_tuple, other)
我的__hash__()
函数被实现为返回被保持的tuple
的哈希值,即:
def __hash__(self):
return hash(self.member_tuple)
基本上,__cmp__()
和__hash__()
如何互动?我不知道__cmp__()
other
中tuple
是否已经是哈希,我是否应该与#34;我的"哈希(可以是持有的self
)或反对{{1}}。
哪一个是正确的?
任何人都可以对此有所了解并可能指出我的文件吗?
答案 0 :(得分:5)
我不会使用__cmp__
而是坚持使用__eq__
代替。对于散列是足够的,你不想扩展到这里可排序。此外,{3}已从Python 3中移除,以支持丰富的比较方法(__cmp__
,__eq__
,__lt__
等。)
接下来,当成员元组相等时,__gt__
应返回True:
__eq__
当def __eq__(self, other):
if not isinstance(other, ThisClass):
return NotImplemented
return self.member_tuple == other.member_tuple
对象的类型不相同时返回NotImplemented
单例是一种很好的做法,因为它会将相等性测试委托给other
对象;如果它没有实现other
或者还返回__eq__
,Python将回退到标准NotImplemented
测试。
您的id()
实施工作正在进行中。
因为哈希不是唯一的(它只是在哈希表中选择一个槽的一种方法),所以使用相等来确定匹配的密钥是否已经存在或者是否发生了哈希冲突。因此,如果对象被散列到的插槽为空,则不会调用__hash__
(如果缺少__eq__
,则调用__cmp__
。
这意味着如果两个对象被认为是相等的(__eq__
返回a.__eq__(b)
),那么它们的哈希值也必须相等。否则你最终会得到一个损坏的字典,因为Python将无法再确定哈希表中是否已存在密钥。
如果您的True
和__eq__
方法都将其职责委托给__hash__
属性,那么您正在维护该属性;您可以信任基本self.member_tuple
类型以正确实现此目的。
请参阅glossary definition of hashable和object.__hash__()
documentation。如果您感到好奇,我已经写过tuple
和dict
类型如何在内部工作: