内置Python hash()函数

86 投票
10 回答
109310 浏览
提问于 2025-04-15 11:16

Windows XP,Python 2.5:

hash('http://stackoverflow.com') Result: 1934711907

谷歌应用引擎(http://shell.appspot.com/):

hash('http://stackoverflow.com') Result: -5768830964305142685

这是为什么呢?我怎样才能得到一个哈希函数,让它在不同的平台上(Windows、Linux、Mac)都能给我相同的结果呢?

10 个回答

32

这个回答一点也不意外:实际上

In [1]: -5768830964305142685L & 0xffffffff
Out[1]: 1934711907L

所以如果你想要对ASCII字符串获得可靠的结果,直接取低32位作为uint就可以了。这个字符串的哈希函数是32位安全的,并且几乎可以在不同平台上使用。

另一方面,你不能指望对任何没有明确定义__hash__方法的对象获取稳定的hash()值。

对于ASCII字符串之所以有效,是因为哈希是基于构成字符串的单个字符计算的,像下面这样:

class string:
    def __hash__(self):
        if not self:
            return 0 # empty
        value = ord(self[0]) << 7
        for char in self:
            value = c_mul(1000003, value) ^ ord(char)
        value = value ^ len(self)
        if value == -1:
            value = -2
        return value

其中c_mul函数是“循环”乘法(没有溢出),就像在C语言中一样。

93

根据文档的说明,内置的 hash() 函数 并不是 用来将生成的哈希值存储到外部的。它的主要作用是提供对象的哈希值,以便将这些值存储在字典等数据结构中。而且,这个函数的具体实现可能会有所不同(比如 GAE 使用的是修改过的 Python 版本)。你可以看看:

>>> class Foo:
...     pass
... 
>>> a = Foo()
>>> b = Foo()
>>> hash(a), hash(b)
(-1210747828, -1210747892)

正如你所看到的,它们是不同的,因为 hash() 使用的是对象的 __hash__ 方法,而不是像 SHA 这样的“正常”哈希算法。

基于以上原因,比较合理的选择是使用 hashlib 模块。

61

使用 hashlib,因为 hash() 是为了:

在查找字典时快速比较字典的键

所以它并不能保证在不同的Python版本中结果是一样的。

撰写回答