【问题标题】:What's the logic behind Python's hash function order?Python的哈希函数顺序背后的逻辑是什么?
【发布时间】:2015-08-12 18:19:27
【问题描述】:

众所周知,Python 的一些数据结构使用 哈希表 来存储 setdictionary 等项目。所以这些对象没有顺序。但是,对于某些数字序列,这似乎是不正确的。

例如考虑以下示例:

>>> set([7,2,5,3,6])
set([2, 3, 5, 6, 7])

>>> set([4,5,3,0,1,2])
set([0, 1, 2, 3, 4, 5])

但是如果我们做一个小改动,它就不会被排序:

>>> set([8,2,5,3,6])
set([8, 2, 3, 5, 6])

那么问题来了:Python 的哈希函数是如何处理整数序列的?

【问题讨论】:

  • “未排序”并不意味着“永远不会出现排序”;它只是意味着没有特定的保证顺序。
  • 有趣的事实:go 作者决定主动随机化这些数据结构的迭代,以提醒用户对其顺序没有任何保证。 blog.golang.org/go-maps-in-action(在“迭代顺序”下)

标签: python python-3.x python-2.7 hashtable python-internals


【解决方案1】:

虽然SO中有很多关于hash及其顺序的问题,但没有一个解释哈希函数的算法。

所以你只需要知道python如何计算哈希表中的索引。

如果您浏览 CPython 源代码中的 hashtable.c 文件,您将在 _Py_hashtable_set 函数中看到以下行,它显示了 python 计算哈希表键索引的方式:

key_hash = ht->hash_func(key);
index = key_hash & (ht->num_buckets - 1);

因此,由于整数的哈希值是整数本身 *(-1 除外),因此索引基于数据结构 (ht->num_buckets - 1) 的数量和长度,它使用按位计算,介于 @987654327 之间@ 和数字。

现在考虑以下使用哈希表的 set 示例:

>>> set([0,1919,2000,3,45,33,333,5])
set([0, 33, 3, 5, 45, 333, 2000, 1919])

对于号码33,我们有:

33 & (ht->num_buckets - 1) = 1

其实是这样的:

'0b100001' & '0b111'= '0b1' # 1 the index of 33

注意在这种情况下,(ht->num_buckets - 1)8-1=70b111

对于1919

'0b11101111111' & '0b111' = '0b111' # 7 the index of 1919

对于333

'0b101001101' & '0b111' = '0b101' # 5 the index of 333

以及前面的例子:

>>> set([8,2,5,3,6])
set([8, 2, 3, 5, 6])

'0b1000' & '0b100'='0b0' # for 8
'0b110' & '0b100'='0b100' # for 8

* int 类的哈希函数:

class int:
    def __hash__(self):
        value = self
        if value == -1:
            value = -2
        return value

【讨论】:

  • 在你的代码 sn-p 末尾有一个小错误:value == -2 不会将-2 分配给value,并且也会始终产生False,因为我们检查是否@987654347 @ 在上一行。由于编辑少于6个字符,我无法自己制作。
  • 在你最后给出的例子中,你似乎假设ht->num_buckets 等于集合中的项目数。这不是真的:桶的数量是 2 的幂,并且通常显着大于集合中的项目数(实际上,对于所有或几乎所有要填充的桶的哈希冲突是不利的;启发式Python 使用的是在哈希表变满 2/3 后扩大哈希表)。
  • @MarkDickinson 是的,我是这样想的。这很有趣,但是作为项目大小(对于桶)有什么问题?您能否解释一下 Cpython 如何计算存储桶的数量,以便我可以用正确的信息更新我的答案?
猜你喜欢
  • 1970-01-01
  • 2015-07-31
  • 1970-01-01
  • 2022-08-14
  • 2020-09-08
  • 1970-01-01
  • 2018-06-18
  • 2020-05-22
相关资源
最近更新 更多