Python 的哈希函数在不同版本中保持相同吗?

问题描述 投票:0回答:3

我目前正在整数和字符串的元组(以及整数和字符串的嵌套元组等)上使用

hash
来计算某些对象的唯一性。除非可能存在哈希冲突,我想知道 - 这些数据类型上的
hash
函数是否保证为不同版本的 Python 返回相同的结果?

python hash compatibility backwards-compatibility
3个回答
19
投票

不。除了 32 位和 64 位版本的 Python 之间长期存在的差异之外,哈希算法在 Python 3.3 中进行了更改以解决安全问题:

默认情况下,str、bytes 和 datetime 对象的 hash() 值会使用不可预测的随机值进行“加盐”。尽管它们在单个 Python 进程中保持不变,但在重复调用 Python 之间它们是不可预测的。

这是为了防止由于精心选择的输入而导致的拒绝服务,这些输入利用了字典插入的最坏情况性能,复杂度为 O(n^2)。有关详细信息,请参阅 http://www.ocert.org/advisories/ocert-2011-003.html

更改哈希值会影响字典、集合和其他映射的迭代顺序。 Python 从未对这种顺序做出保证(并且它通常在 32 位和 64 位版本之间有所不同)。

因此,从 3.3 开始

hash()
甚至不能保证在同一 Python 版本的不同调用中返回相同的结果。


10
投票

我不确定你在寻找什么,但如果你正在寻找一致的哈希,你可以随时使用

hashlib

>>> import hashlib
>>> t = ("values", "other")
>>> hashlib.sha256(str(t).encode("utf-8")).hexdigest()
'bc3ed71325acf1386b40aa762b661bb63bb72e6df9457b838a2ea93c95cc8f0c'

或:

>>> h = hashlib.sha256()
>>> for item in t:
...     h.update(item.encode("utf-8"))
...
>>> h.hexdigest()
'5e98df135627bc8d98250ca7e638aeb2ccf7981ce50ee16ce00d4f23efada068'

2
投票

不。例如。

32 位

Python 2.7.3 (default, Aug  1 2012, 05:16:07) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> hash("foobar")
-1969371895

64 位

Python 2.7.3 (default, Aug  1 2012, 05:14:39) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> hash("foobar")
3433925302934160649
© www.soinside.com 2019 - 2024. All rights reserved.