我正在尝试为某些对象创建一个自定义哈希函数,我将要深入到字典中。散列函数是唯一的(不是标准的Python函数)。这对我来说非常重要:使用独特的功能。每个键的值都是一个列表。
假设我覆盖__hash__
并最终为对象提供正确的哈希值。将:
dict = {}
dict[number_here] = value
将值散列到位置编号number_here
中,还是仍然位于Python的哈希表为该数字计算的位置?
打印dict
仅显示项目,而不显示它们的位置。但是,当我执行hash(4)
时,结果是4.所以我假设这意味着整数被散列到它们各自的位置?
如果我错了,有人可以验证我的调查结果或向我解释吗?
答案 0 :(得分:12)
python dict
实现使用哈希值来基于密钥稀疏地存储值,并避免该存储中的冲突。它使用hash()
的结果作为起点,它不是最终位置。
因此,尽管hash(4)
返回4
,但底层C结构中的确切“位置”也基于其他键已存在的位置,以及目前的表是。例如,根据需要(添加项目)调整python哈希表的大小。
由于dict没有排序,这不是你需要担心或者希望影响的东西。如果您需要在dict中进行排序,请改用collections.OrderedDict()
实现,它会单独跟踪排序。
您可能想要了解哈希表如何在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)