当键是数字时,我对python中的字典属性有疑问。 在我的情况下,当我用数字键打印字典时,打印结果将按键排序,但在另一种情况下(键是字符串)字典是无序的。我想在字典中了解这条规则。
l = {"one" : "1", "two" : "2", "three" : "3"}
print(l)
l = {1: "one", 2: "two", 3: "three", 4: "four", 5: "five"}
print(l)
l = {2: "two", 3: "three", 4: "four", 1: "one", 5: "five"}
print(l)
结果:
{'three': '3', 'two': '2', 'one': '1'}
{1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'}
{1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'}
答案 0 :(得分:1)
Python使用hash table来存储字典,因此在字典或其他使用哈希函数的对象中没有排序。
但是关于散列对象中的项目索引,python根据以下代码within hashtable.c
计算索引:
key_hash = ht->hash_func(key);
index = key_hash & (ht->num_buckets - 1);
因为整数的哈希值本身就是整数,所以索引是基于数字(ht->num_buckets - 1
是一个常数)所以索引是按比特计算的,并且在(ht->num_buckets - 1)
和数字之间。< / p>
请考虑以下使用hash-table的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=7
或0b111
。
对于1919
:
'0b11101111111' & '0b111' = '0b111' # 7 the index of 1919
对于333
:
'0b101001101' & '0b111' = '0b101' # 5 the index of 333
有关python哈希函数的更多详细信息,请阅读python source code中的以下引用:
未来的主要微妙之处:大多数哈希方案依赖于具有“好”哈希 功能,在模拟随机性的意义上。 Python不是:它最多 重要的哈希函数(对于字符串和整数)是非常规律的 例:
>>> map(hash, (0, 1, 2, 3)) [0, 1, 2, 3] >>> map(hash, ("namea", "nameb", "namec", "named")) [-1658398457, -1658398460, -1658398459, -1658398462]
这不一定是坏事!相反,在一张大小为2 ** i的表中,采取 作为初始表索引的低阶i位非常快,并且存在 对于由连续的整数范围索引的词组,完全没有冲突。 当键是“连续”字符串时,大致相同。所以这 在常见情况下提供优于随机的行为,这是非常可取的。
OTOH,当发生碰撞时,倾向于填充连续的切片 哈希表使得良好的冲突解决策略至关重要。只服用 哈希码的最后一位也很脆弱:例如,考虑一下 列表[i << 16 for i in range(20000)]
作为一组键。 由于int是他们自己的哈希码,并且这适合于大小为2 ** 15的dict,每个哈希码的最后15位都是0:他们 all 映射到同一个表索引。强>但迎合不寻常的情况不应该减慢通常情况,所以我们只是采取 无论如何,最后的i位。其余部分取决于碰撞解决方案。如果 我们通常在第一次尝试时找到我们正在寻找的钥匙(而且,它会变成 我们通常做 - 表负载系数保持在2/3以下,所以赔率 坚定地支持我们,然后最好保留初始索引 计算污垢便宜。