如何为我的类实现__cmp __()和__hash __()?

时间:2014-12-12 13:01:39

标签: python dictionary hash collections python-2.x

我想写一个可以用作可散列集合中的键的类(例如在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__() othertuple是否已经是哈希,我是否应该与#34;我的"哈希(可以是持有的self)或反对{{1}}。

哪一个是正确的?

任何人都可以对此有所了解并可能指出我的文件吗?

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 hashableobject.__hash__() documentation。如果您感到好奇,我已经写过tupledict类型如何在内部工作: