在字典中覆盖Python的哈希函数

时间:2012-11-22 14:24:39

标签: python hash dictionary hashtable

我正在尝试为某些对象创建一个自定义哈希函数,我将要深入到字典中。散列函数是唯一的(不是标准的Python函数)。这对我来说非常重要:使用独特的功能。每个键的值都是一个列表。

假设我覆盖__hash__并最终为对象提供正确的哈希值。将:

dict = {}
dict[number_here] = value

将值散列到位置编号number_here中,还是仍然位于Python的哈希表为该数字计算的位置?

打印dict仅显示项目,而不显示它们的位置。但是,当我执行hash(4)时,结果是4.所以我假设这意味着整数被散列到它们各自的位置?

如果我错了,有人可以验证我的调查结果或向我解释吗?

2 个答案:

答案 0 :(得分:12)

python dict实现使用哈希值来基于密钥稀疏地存储值,并避免该存储中的冲突。它使用hash()的结果作为起点,它不是最终位置。

因此,尽管hash(4)返回4,但底层C结构中的确切“位置”也基于其他键已存在的位置,以及目前的表是。例如,根据需要(添加项目)调整python哈希表的大小。

由于dict没有排序,这不是你需要担心或者希望影响的东西。如果您需要在dict中进行排序,请改用collections.OrderedDict()实现,它会单独跟踪排序。

python哈希表实现的详细信息

您可能想要了解哈希表如何在Wikipedia上运行; Python使用开放寻址来实现它。

在表中选择一个插槽时,将获取散列值(整数)和当前表大小的模数,因此在大小为32的表上,因此键45,散列值{{ 1}}最初将存储在插槽14中。

如果发生冲突(插槽14中已存在其他内容并且它不是整数45),则插槽值被扰乱,直到找到空插槽或找到相同的密钥。 Perturbing用公式完成:

45

因此,当发生碰撞时,以逐渐变小的步骤拾取另一个槽,直到它扫描整个表。请注意,如果需要,表格已经调整大小以腾出空间。

为了使其正常工作,自定义类型需要__hash__()方法都需要实现__eq__()来确定两个实例是否代表相同的密钥。匹配的哈希值不足。对于perturb = slot = hash while slot_is_full and item_in_slot_is_not_equal_to_key: slot = (5*slot) + 1 + perturb perturb >>= 5 实现,要考虑两个实例来表示完全相同的键,它们的哈希值必须匹配,并且它们必须为dict相等运算符返回True。这些对象被视为hashable

(对于Python 2.x,实现__cmp__() hook而不是实现==;在Python 3中已经删除了对此的支持。

答案 1 :(得分:1)

Martijn Pieters给出了一个很好的答案。我只是想补充说CPython source有很好的文档记录,也是查看Python Dictionary实现细节的好地方。最后我查了一下,相关的评论是在第33-135行。