密钥是数字时的python词典

时间:2015-05-29 14:28:33

标签: python-3.x dictionary numbers key

当键是数字时,我对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'}

1 个答案:

答案 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=70b111

对于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以下,所以赔率   坚定地支持我们,然后最好保留初始索引   计算污垢便宜。