这是python的内置哈希函数的恰当使用吗?

时间:2011-10-04 10:31:03

标签: python hash hash-collision

我需要比较大块数据的相等性,我需要每秒比较很多,快速。每个对象都保证大小相同,并且可能/可能只是略有不同(在未知位置)。

我已经看到,从下面的交互式会话中,如果差异在字符串的末尾,则使用==运算符的字节字符串可能会更慢,如果在字符串末尾附近存在差异,则可能会非常快开始。

我认为可能有某种方法可以使用某种哈希来加快速度,当然计算md5哈希值并且比较速度慢,但是python的内置哈希确实显着加快了速度。

但是,我不知道这个哈希的实现细节,它是否真的像哈希一样,我觉得hash(a) == hash(b)然后a == b非常可能?如果哈希冲突相当罕见,我很高兴有一些不正确的结果(在需要an array of 200 PS3s several hours to make a collision的意义上很少见)

In [1]: import hashlib

In [2]: with open('/dev/urandom') as f:
   ...:     spam = f.read(2**20 - 1)
   ...:     

In [3]: spamA = spam + 'A'

In [4]: Aspam = 'A' + spam

In [5]: spamB = spam + 'B'

In [6]: timeit spamA == spamB
1000 loops, best of 3: 1.59 ms per loop

In [7]: timeit spamA == Aspam
10000000 loops, best of 3: 66.4 ns per loop

In [8]: timeit hashlib.md5(spamA) == hashlib.md5(spamB)
100 loops, best of 3: 4.42 ms per loop

In [9]: timeit hashlib.md5(spamA) == hashlib.md5(Aspam)
100 loops, best of 3: 4.39 ms per loop

In [10]: timeit hash(spamA) == hash(spamB)
10000000 loops, best of 3: 157 ns per loop

In [11]: timeit hash(spamA) == hash(Aspam)
10000000 loops, best of 3: 160 ns per loop

1 个答案:

答案 0 :(得分:28)

Python的哈希函数是为速度而设计的,并映射到64位空间。由于birthday paradox,这意味着您可能会在大约50亿个条目中发生冲突(可能更早,因为散列函数不是加密的)。此外,hash的精确定义取决于Python实现,可能是体系结构甚至是机器特定的。不要在多台机器上使用它,你想要相同的结果。

md5被设计为加密哈希函数;即使输入中的轻微扰动也会完全改变输出。它还映射到一个128位的空间,这使得你根本不可能遇到任何碰撞,除非你专门寻找一个。

如果你可以处理冲突(即测试存储桶中所有成员之间的相等性,可能使用像MD5或SHA2这样的加密算法),Python的哈希函数就可以了。

还有一件事:为了节省空间,如果将数据写入磁盘,则应以二进制形式存储数据。 (即struct.pack('!q', hash('abc')) / hashlib.md5('abc').digest())。

作为旁注:is不等同于Python中的==。你的意思是==