为啥 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 值的引用(即函数参数)存储在 CPython 的堆栈(帧)中?