Python 的哈希函数顺序背后的逻辑是什么?
What's the logic behind Python's hash function order?
我们知道,Python 的一些数据结构使用 哈希表 来存储 set
或 dictionary
等项目。所以这些对象没有顺序。但似乎,对于某些数字序列,情况并非如此。
例如考虑以下示例:
>>> 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 的哈希函数如何处理整数序列?
虽然SO里面有很多关于hash
及其顺序的问题,但是没有一个解释hash函数的算法。
所以你在这里只需要知道 python 如何计算散列中的索引 table.
如果你浏览 CPython 源代码中的 hashtable.c
文件,你会在 _Py_hashtable_set
函数中看到以下行,它显示了 python 计算散列索引的方式 table键:
key_hash = ht->hash_func(key);
index = key_hash & (ht->num_buckets - 1);
因此,由于整数的哈希值是整数本身 *(-1 除外),索引基于数字和数据结构的长度(ht->num_buckets - 1
),并使用 Bitwise- 计算在 (ht->num_buckets - 1)
和数字之间。
现在考虑以下 set
的示例,该示例使用 hash-table :
>>> 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=7
或 0b111
。
对于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
* class int
的哈希函数:
class int:
def __hash__(self):
value = self
if value == -1:
value = -2
return value
我们知道,Python 的一些数据结构使用 哈希表 来存储 set
或 dictionary
等项目。所以这些对象没有顺序。但似乎,对于某些数字序列,情况并非如此。
例如考虑以下示例:
>>> 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 的哈希函数如何处理整数序列?
虽然SO里面有很多关于hash
及其顺序的问题,但是没有一个解释hash函数的算法。
所以你在这里只需要知道 python 如何计算散列中的索引 table.
如果你浏览 CPython 源代码中的 hashtable.c
文件,你会在 _Py_hashtable_set
函数中看到以下行,它显示了 python 计算散列索引的方式 table键:
key_hash = ht->hash_func(key);
index = key_hash & (ht->num_buckets - 1);
因此,由于整数的哈希值是整数本身 *(-1 除外),索引基于数字和数据结构的长度(ht->num_buckets - 1
),并使用 Bitwise- 计算在 (ht->num_buckets - 1)
和数字之间。
现在考虑以下 set
的示例,该示例使用 hash-table :
>>> 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=7
或 0b111
。
对于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
* class int
的哈希函数:
class int:
def __hash__(self):
value = self
if value == -1:
value = -2
return value