Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';这是Python背后的逻辑';s哈希函数顺序?_Python_Python 3.x_Python 2.7_Hashtable_Python Internals - Fatal编程技术网

什么';这是Python背后的逻辑';s哈希函数顺序?

什么';这是Python背后的逻辑';s哈希函数顺序?,python,python-3.x,python-2.7,hashtable,python-internals,Python,Python 3.x,Python 2.7,Hashtable,Python Internals,正如我们所知,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])

正如我们所知,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中有很多关于哈希及其顺序的问题,但是没有人解释哈希函数的算法

所以这里您只需要知道python如何计算哈希表中的索引

如果在CPython源代码中浏览该文件,您将在
\u Py\u hashtable\u set
函数中看到以下几行,该函数显示python计算哈希表键索引的方式:

key_hash = ht->hash_func(key);
index = key_hash & (ht->num_buckets - 1);
因此,由于整数的散列值是整数本身*(除-1外),因此索引基于数据结构的数量和长度(
ht->num_bucket-1
),并在
(ht->num_bucket-1)
和数字之间按位和进行计算

现在考虑下面的例子,使用<哈希表:

<代码> >:
>>> 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_bucket-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

*类
int
的哈希函数:

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

“未排序”并不意味着“永远不会显示为排序”;有趣的事实是:
go
作者决定在这些数据结构上主动随机迭代,以提醒用户其顺序没有保证。(在“迭代顺序”下)您的代码段末尾有一个小错误:
value==-2
不会将
-2
分配给
value
,而且也总是会产生
False
,因为我们在前一行检查
value==-1
。由于编辑少于6个字符,我自己无法编辑。在您最后给出的示例中,您似乎假设
ht->num_bucket
等于集合中的项目数。事实并非如此:存储桶的数量是2的幂,通常比集合中的项目数量大得多(事实上,对于所有或几乎所有要填充的存储桶来说,这对哈希冲突是有害的;Python使用的启发式方法是在哈希表满了2/3后将其放大)。@MarkDickinson是的,我是这样认为的。这很有趣,但是作为物品的大小(用于桶)有什么问题?你能解释一下Cpython是如何计算桶数的,这样我就可以用正确的信息更新我的答案了吗?