为啥 CPython 字典不受负一和负二的哈希值的影响

Posted

技术标签:

【中文标题】为啥 CPython 字典不受负一和负二的哈希值的影响【英文标题】:Why aren't CPython Dicts affected by Hash Values for Negative one and negative two为什么 CPython 字典不受负一和负二的哈希值的影响 【发布时间】:2013-12-07 23:48:40 【问题描述】:

Hash tables are supposed be high-performance mappings、and because Python dicts are implemented with hash tables,它们的性能也很高。但是我在查看负整数的哈希值时遇到了一个奇怪的结果。

>>> for i in range(7):
...     print hash(i-4)
...     
-4
-3
-2
-2
0
1
2

但这显然对dicts没有影响:

>>> d = dict()
>>> d[-1] = 'foo'
>>> d[-2] = 'bar'
>>> d
-2: 'bar', -1: 'foo'

为什么会发生这种情况,为什么我使用 dicts 时不受影响?

【问题讨论】:

【参考方案1】:

如果你问为什么 dicts 不受重复哈希值的影响,那是因为哈希值不需要是唯一的哈希表才能工作。

Python 实现了简单的整数散列,其中整数的散列值解析为自身。由于 -1 在内部用于表示生成哈希值失败,因此值 -1 会被 -2 静默替换,这同样有效。

【讨论】:

【参考方案2】:

-1 是 C 代码中的错误代码,没有哈希函数可以返回它,以免它指示 C 代码错误。 C 没有异常,因此 Python 开发人员必须保留 一个 返回值以发出错误信号。

字典不使用只是一个哈希;它还测试是否相等。请注意,与可能的哈希值的数量相比,哈希表,即使哈希值相等,它们仍然可以最终映射到同一个槽。如果一个hash值映射到同一个slot,并且key不相等,那么hash就会被扰动,找到一个新的slot。

因为-1 != -2,Python 仍然将两个键分开。

有关 Python 字典如何使用哈希的更多详细信息,请参阅 Overriding Python's Hashing Function in Dictionary 和 Why is the order in dictionaries and sets arbitrary?。

【讨论】:

【参考方案3】:

x 具有与y 不同的哈希值这一事实意味着x != y。但反之则不然!因此,当x 的哈希值等于y 时,它们仍然会被明确地检查是否相等。

hash(x) == hash(y)x != y 在散列函数的上下文中被称为冲突,这种情况可能会不时发生。你想尽可能地避免它,但总的来说这是不可避免的。你可以阅读更多关于哈希函数和冲突here。

【讨论】:

【参考方案4】:

哈希表在哈希值不同时表现更好,但它们可以处理相同的哈希值。这些被称为哈希冲突,处理它们的方法是优化和调整哈希表的重要方法之一。

hash(-1) == -2 因为 -1 是一个特殊值,用于在 C 实现中表示错误。哈希码不能取那个值;如果你尝试定义一个哈希值为 -1 的类,Python 会检测到它并使用 -2 代替。

【讨论】:

以上是关于为啥 CPython 字典不受负一和负二的哈希值的影响的主要内容,如果未能解决你的问题,请参考以下文章

python 字典为啥这么快

为啥对 Python 值的引用(即函数参数)存储在 CPython 的堆栈(帧)中?

考研英语一和y英语二的区别

为啥即使哈希函数可能不是 O(1),也要通过键 O(1) 访问字典的元素?

python 中关于字典的键

怎样算次幂啊