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

0xC*_*22L 3 python collections hash dictionary python-2.x

我想编写一个可以用作可散列集合中的键的类(例如,在a中dict).我知道用户类默认id(self)是可以使用的,但在这里使用是错误的.

我的类拥有一个tupleas成员变量.派生tuple似乎不是一个选项,因为在我的构造函数中,我没有得到与构造函数相同的参数tuple.但也许这不是限制?

我需要的基本上是tuple一个真正的元组给它的方式的哈希.

hash(self.member_tuple) 做到了那一点.

这里的想法是两个元组可以相等而不id相等.

如果我__cmp__()按如下方式执行:

def __cmp__(self, other):
    return cmp(self, other)
Run Code Online (Sandbox Code Playgroud)

这会自动求助于hash(self)比较吗?......或者我应该按如下方式实施:

def __cmp__(self, other):
    return cmp(self.member_tuple, other)
Run Code Online (Sandbox Code Playgroud)

我的__hash__()函数被实现为返回被保持的哈希值tuple,即:

def __hash__(self):
    return hash(self.member_tuple)
Run Code Online (Sandbox Code Playgroud)

基本上,如何做__cmp__()__hash__()互动?我不知道是否__cmp__()other将已经是一个哈希与否,我是否应该比较对"我"的哈希(这将是的举行的一个tuple),或反对self.

那么哪一个是正确的呢?

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

Mar*_*ers 5

我不会使用__cmp__并坚持使用__eq__.对于散列是足够的,你不想扩展到这里可排序.此外,__cmp__已经从Python 3的赞成富比较方法(除去__eq__,__lt__,__gt__等等).

接下来,__eq__当成员元组相等时,您应该返回True:

def __eq__(self, other):
    if not isinstance(other, ThisClass):
        return NotImplemented
    return self.member_tuple == other.member_tuple
Run Code Online (Sandbox Code Playgroud)

NotImplementedother对象的类型不相同时返回单例是很好的做法,因为它会将相等测试委托给other对象; 如果它没有实现__eq__或者也返回NotImplementedPython将回退到标准id()测试.

您的__hash__实施是正确的.

因为哈希不是唯一的(它只是在哈希表中选择一个槽的一种方法),所以使用相等来确定匹配键是否已经存在或者是否发生了哈希冲突.作为这种__eq__(或__cmp__如果__eq__丢失)不如果要将对象被散列化槽是空的调用.

这意味着如果两个对象被认为是相等的(a.__eq__(b)返回True),那么它们的哈希值也必须相等.否则,您最终可能会损坏字典,因为Python将无法再确定哈希表中是否已存在密钥.

如果您__eq____hash__方法都将其职责委托给self.member_tuple属性,那么您将维护该属性; 您可以信任基本tuple类型以正确实现此功能.

请参阅hashable术语表定义object.__hash__()文档.如果你很好奇,我已经写过内部dictset类型如何工作: