为什么-1,-2 CPython的两个哈希-2? [重复] 为什么-1,-2 CPython的两

2019-05-13 12:34发布

可能重复:
当一个Python对象的哈希计算,为什么是-1不同的哈希?

为什么-1-2都哈希到同一个号码,如果Python的?

既然他们这样做,Python是怎样分辨这两个数字?

>>> -1 is -2
False
>>> hash(-1) is hash(-2)
True
>>> hash(-1)
-2
>>> hash(-2)
-2

Answer 1:

-1是在CPython的的C水平,其防止散列函数从能够产生的散列值的保留值-1 。 正如帝斯曼指出,同样是不正确的IronPython和PyPy其中hash(-1) != hash(-2)

见这Quora的答案 :

如果你写一个C扩展模块中的类型,并提供一个tp_hash方法,你必须避免-1 -如果返回-1 ,Python会假定你的意思是抛出一个错误。

如果你写在纯Python类,并提供一个__hash__方法,有没有这样的规定,谢天谢地。 但是,这是因为调用你的C代码__hash__方法会为你-如果你的__hash__返回-1 ,则hash()应用到你的对象实际上将返回-2

这真的只是从重新打包的信息effbot :

哈希值-1被保留(它是用来标记错误的C实现)。 如果散列算法生成此值,我们简单地使用-2代替。

您还可以看到这个源。 例如,对于Python 3中的int对象,这是在端部的散列执行 :

if (x == (Py_uhash_t)-1)
    x = (Py_uhash_t)-2;
return (Py_hash_t)x;

既然他们这样做,Python是怎样分辨这两个数字?

因为所有哈希函数映射一个大的输入空间,以更小的输入空间,碰撞总是预期,哈希函数再好的。 想想散列字符串,例如。 如果散列码是32位整数,你有2 ^ 32(略超过4十亿)的散列码。 如果考虑长度为6的所有ASCII字符串,你有(2 ^ 7)^ 6(不到4.4万亿),不同的项目在你的输入空间。 由于只有这一套,你保证有很多很多的碰撞不管你有多好。 加入Unicode字符和无限长度的字符串到!

因此,散列代码只暗示一个对象的位置,一个相等测试如下测试候选键。 为了实现在哈希表集的成员资格测试,哈希码给出其中搜索的价值你“斗”号。 然而,相同的散列码所有设置项目都在斗。 对于这一点,你还需要一个平等的测试在桶中的所有考生进行区分。

该散列码与平等偶是在暗示中的哈希的对象CPython的文档 。 在其他语言/框架,有一个准则/规则,如果你提供一个自定义的散列码功能,还必须提供自定义的平等测试(在相同的字段作为哈希函数的代码执行)。


事实上,Python的今天发布的地址正是这一点,与当这(散列值相同,但大规模)作为服务拒绝攻击,解决效率问题,安全补丁- http://mail.python.org /pipermail/python-list/2012-April/1290792.html



文章来源: Why do -1 and -2 both hash to -2 in CPython? [duplicate]