Python冻结集合的持久哈希

5 投票
2 回答
1074 浏览
提问于 2025-04-17 09:02

你怎么把一堆嵌套的Python frozenset对象转换成一个独特的整数,这个整数在不同的Python会话和平台上都是一样的呢?

比如说,我在不同的平台上用hash()得到的值是不一样的。

32位

Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a=frozenset([frozenset([1,2,3]),frozenset(['a','b','c'])]);
>>> hash(a)
1555175235

64位

Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a=frozenset([frozenset([1,2,3]),frozenset(['a','b','c'])]);
>>> hash(a)
-6076998737938213053

2 个回答

0

你也可以自己创建一个哈希函数:

def hash(fs):
    res = 1
    for v in fs:
        res = (res*31 + v) % 2**30
    return res

这个哈希函数不一定是唯一的,但它和内置的集合哈希函数差不多好,而且你可以完全控制它在不同平台上的结果。

8

你如何将一堆嵌套的Python frozenset对象转换成一个在不同Python会话和平台上都相同的唯一整数呢?

据我所知,哈希值并不一定是唯一的。实际上,在查找表(比如字典)中,哈希冲突是很常见的。

不过,如果你想要一个在不同平台上都一致的、但不一定唯一的“哈希”,我建议你使用标准库中的hashlib。我没有机会在不同的平台上试验,但我相信那里的大多数算法(比如MD5)都是与平台无关的。

我会将排序后的集合的序列化版本输入到哈希算法中,这样可以确保用于哈希的字符串始终是相同的。


编辑:我想加一个基本的例子:

>>> import cPickle as pkl
>>> import hashlib as hl
>>> s = frozenset([1,2,3])
>>> p = pkl.dumps(sorted(s))  #make sure you use the same pickle protocol on all platform!
'(lp1\nI1\naI2\naI3\na.'
>>> h = hl.md5(p)
<md5 HASH object @ 0xb76fb110>
>>> h.digest()
"\x89\xaeG\x1d'\x83\xa5\xbd\xac\xa7\x1c\xd9\x1d/2t"  #this should be consistent

撰写回答