python dict实现细节

时间:2015-02-21 06:01:38

标签: python

我对python字典实现有疑问。

看起来python将维护所有密钥的搜索顺序,例如 如果您执行以下操作

a = {}
a[3] = 1
a[0] = 2

a = {0:2, 3:1}

python会自动更改我的广告订单。 由于python声称dict是无序的,所以我并不完全 理解为什么python会维护这样的搜索顺序。 python是否通过哈希表实现dict并存储另一个 为索引排序设置?

希望我明白这个问题。

谢谢

2 个答案:

答案 0 :(得分:17)

dict的顺序完全取决于对象的散列函数(如果存在散列碰撞,则为插入顺序)。整数哈希自己(至少高达sys.maxint):

>>> hash(1)
1

(C)python实现获取对象的哈希值,并使用几位来确定表中的索引。它需要多少位取决于字典的长度。默认情况下,dict有8个可用插槽,因此数字08会发生冲突。我们可以看到如下:

>>> d1 = {}
>>> d1[0] = 'foo'
>>> d1[8] = 'bar'
>>> d1
{0: 'foo', 8: 'bar'}
>>>
>>> d2 = {}
>>> d2[8] = 'bar'
>>> d2[0] = 'foo'
>>> d2
{8: 'bar', 0: 'foo'}

由于08在我们的字典中发生冲突,因此插入顺序似乎已被维护。 0占用了第一个可用的广告位(毕竟,无论您从0获得多少位,您都会获得0)。 8也尝试占用该位置。但是,如果采用该槽,则冲突解决将接管并且python会在稍后的某个插槽中插入该值。

当然,如果你的词典恰好有超过5个元素,那么它将被调整大小(我认为是16,但不要引用我)和0和{{1}将不再碰撞...

8

注意,(已排序)顺序被保留(不是插入顺序),这意味着每个整数都在哈希表中得到它的首选点(没有冲突)。我认为当大约2 / 3rds满时,dict会被调整大小。


请注意,这纯粹是学术性的 - python规范并没有说它是如何工作的,所以它可以随时改变。请不要依赖这种行为。其中大部分可以从旁边的comments in the source codedocumentation收集......

答案 1 :(得分:1)

Dict索引排序只是dict如何实现的结果,不应该依赖。

准确地说,Python不会更改您的插入顺序(因为它只是定义为将项目插入到dict中的顺序),但迭代顺序无法保证。

当Python创建一个dict时,它为8个键值对创建了足够的空间(我认为)。对于一个空的字典,它们都没有被填满。每当你将一个项放入一个dict时,Python就会获取一个键的哈希值,而key的哈希值决定了该索引的内容。

如果您确实希望迭代顺序与广告订单顺序相同,请查看ordereddict