使用对象的id()作为哈希值

时间:2019-03-10 08:47:42

标签: python hash

像这样实现size()是一个坏主意吗?

function uniqueWordCount(str) { 
  let set = new Set(str.split(' '));
  return set.size;
}
console.log(uniqueWordCount('as as de we re'))

我是否设置了可能造成灾难性的损失?

3 个答案:

答案 0 :(得分:4)

__hash__方法必须满足以下要求才能起作用:

将x,y依次为x == y,然后为hash(x) == hash(y)

在您的情况下,您的类未实现__eq__,这意味着x == y当且仅当id(x) == id(y)时,因此哈希实现满足上述属性。

但是请注意,如果您执行实施__eq__,则此实施可能会失败。

也:具有“有效” __hash__和具有 good 哈希值之间是有区别的。例如,以下是 any 类的有效__hash__定义:

def __hash__(self):
    return 1

一个好的散列应该尝试均匀地分布对象,以尽可能避免冲突。通常,这需要更复杂的定义。 我会避免尝试提出公式,而要依靠python内置的hash函数。

例如,如果您的班级有abc字段,那么我将使用类似__hash__的名称:

def __hash__(self):
    return hash((self.a, self.b, self.c))

对于元组,hash的定义应足以满足一般情况。

最后:您不应该在可变的类中定义__hash__(在用于相等性的字段中)。那是因为修改实例会改变其哈希值,这会破坏事情。

答案 1 :(得分:3)

这是毫无意义的还是错误的,具体取决于课程的其余部分。

如果您的对象使用默认的基于身份的==,则定义此__hash__是没有意义的。默认的__hash__也是基于身份的,但是速度更快,并且进行了调整,以避免始终将低位设置为0。使用默认的__hash__会更简单,更高效。

如果您的对象不使用默认的基于身份的==,则您的__hash__是错误的,因为它将与==不一致。如果对象是不可变的,则应以与__hash__一致的方式实现==;如果对象是可变的,则根本不要实现__hash__(如果需要支持Python 2,请设置__hash__ = None。)

答案 2 :(得分:1)

这是__hash__的默认实现。请注意,插入__eq__会导致默认的__hash__实现消失。如果您重新实现__hash__,则所有比较必须的对象必须具有相同的哈希值。

非相等对象也可以具有相同的哈希值。因此,具有返回恒定值的哈希实现始终是安全的。但是,它效率很低。

适用于许多用例的一个很好的默认值是返回__eq__方法中使用的属性的元组的哈希。例如。

class XYZ:
    def __init__(self, val0, val1):
        self.val0 = val0
        self.val1 = val1

    def __eq__(self, other):
        return self.val0 == other.val1 and self.val1 == other.val1

    def __hash__(self):
        return hash((self.val0, self.val1))