内置Python hash()函数
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 模块。