生成并存储随机数作为我的类的哈希值是一个好主意吗?

时间:2011-02-18 21:38:47

标签: python hash

我有一个基本上包装列表的类,列表显然不能有哈希值。我的想法是生成一个随机数并将其存储为哈希值。

4 个答案:

答案 0 :(得分:3)

如果您有两个等效的实例,则它们必须返回相同的__hash__值。如果你随机生成一个,你不能保证会出现这种情况,所以你会得到奇怪的行为。

你可以使用元组而不是列表吗?你能忽略哈希计算中的列表吗?如果不相等的物体发生碰撞,则可以。

您应该看到DictionaryKeys有关不允许列表具有哈希值的原因。

答案 1 :(得分:1)

不是个好主意。哈希码的一般契约是,如果对象A等于对象B,则A.hashCode()等于B.hashCode()。根据你的提议,这不会成立。

您可以尝试使用

  • 将长度列为哈希码
  • 列表中第一项的哈希码作为哈希码
  • 所有项目的所有哈希码的总和为哈希码

或其他类似的东西。

答案 2 :(得分:1)

正如其他人所提到的,如果将2个对象视为“相等”,则它们必须具有相同的散列值。

如何为您的班级定义equals取决于您。如果您只关心引用相等,则可以在__init__上生成随机数,但最好是MyWrapper([1,2,3]) == MyWrapper([1,2,3])False

你不应该将列表内容用作像@iluxa这样的散列的原因是因为如果你使用你的类作为字典中的键,那么改变内容使哈希值改变,它不会能够在字典中找到该密钥,因为它存储了旧的哈希值,并且正在尝试查找新的哈希值。

总结一下:

  1. 如果a == bhash(a) == hash(b)必须为真。
  2. 如果a != b 那么hash(a) != hash(b)应该是 大部分时间都是如此 查找的性能,但确实如此 不一定是这样的。
  3. 的 哈希的值不应该改变 在将它添加到a之间 dict(或任何其他基于哈希的 查找结构没有 在查找时重新计算哈希值) 并试图找到它。
  4. 最后一部分通常只是简化为哈希的值不应该永远改变。

答案 3 :(得分:0)

支持可变容器的散列是合理的 - 但一般规则是你要散列当前值,而不是容器。

编辑原则上这是合理的,尽管Python通常会对此进行防范。

甚至还有针对此类任务的特定散列技术。 Zobrist哈希根据容器的每次更改以递增方式计算哈希值,这样无论您如何达到特定值,都会得到相同的哈希值。这在国际象棋程序中用于检测棋盘通过不同的移动顺序达到相同状态的情况,作为游戏树搜索的优化。

这里的问题是为什么你想使用基于散列的查找找到一个列表?

如果值变化,但是你想要找到相同的容器,那么这可能会起作用(碰撞问题) - 但它似乎仍然毫无意义。随机散列值只是一种标识符,用于标识您所指的对象。对象的引用/指针是更好的标识符。如果您还没有对该对象的引用,您将如何知道要搜索的哈希值?

如果你想要一个容器集合,列表列表是比随机散列列表字典更好的解决方案。

编辑可能的例外情况是,如果您想要一组列表,其中可以多次添加相同的列表,但只会在容器中出现一次 - 一组列表实例。在这种情况下,哈希应该IMO基于对象的引用,但我不记得是怎么做的。