为什么-1和-2在CPython中散列为-2?

可能重复:
什么时候计算出python对象的哈希值,为什么是-1的哈希值是不同的?

为什么-1-2都是散列到相同的数字,如果Python?

既然他们这样做,Python如何将这两个数字分开呢?

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

更新 – 我认为这是一个维基,请随时添加更多的信息。

-1是C级的保留值(CPython – 请参阅DSM关于“如预期的”在ironpython和pypy中的评论)。

看到这个Quora答案 :

如果您在C扩展模块中编写了一个types并提供了一个tp_hash方法,那么您必须避免使用-1 – 如果您返回-1,那么Python将假定您要抛出一个错误。

如果你用纯Python编写一个类并提供一个__hash__方法,那么没有这样的要求,谢天谢地。 但是那是因为调用你的__hash__方法的C代码为你做了这个 – 如果你的__hash__返回-1,那么应用到你的对象的hash()实际上会返回-2。

这真的只是重新包装来自effbot的信息:

散列值-1被保留(用于在C实现中标记错误)。 如果哈希algorithm产生这个值,我们只需要使用-2。

另外,从评论(人们要求更多的信息),来自AGF, 来源 。


既然他们这样做,Python如何将这两个数字分开呢?

由于所有散列函数都将较大的input空间映射到一个较小的input空间,因此无论散列函数的效果如何,总会有冲突。 例如,考虑散列string。 如果散列码是32位整数,则有2 ^ 32(多于40亿个)散列码。 如果考虑到所有长度为6的ASCIIstring,则在input空间中有(2 ^ 7)^ 6(略低于4.4万亿)不同的项目。 只有这样,无论你有多好,你都能保证有多次碰撞。 添加Unicode字符和无限长度的string!

因此,哈希码只提示对象的位置,进行相等性testing以testing候选关键字。 要在散列表集合中实现成员资格testing,散列码将为您提供“存储区”编号,以便在其中search值。 但是,具有相同散列码的所有设置项目都在存储桶中。 为此,你还需要一个平等testing来区分桶中的所有候选人。

这个散列码和相等二元性在CPython文档中对可散列对象进行了暗示。 在其他语言/框架中,有一条指导原则/规则,如果您提供自定义哈希代码函数,则还必须提供自定义相等性testing(在与哈希代码函数相同的字段上执行)。


事实上,今天的Python版本正好解决了这个问题,并且提供了一个安全补丁,当这个(相同的哈希值,但大规模的)被用作拒绝服务攻击时,解决了效率问题 – http://mail.python.org /pipermail/python-list/2012-April/1290792.html