我对python字典实现有疑问。
看起来python将维护所有密钥的搜索顺序,例如 如果您执行以下操作
a = {}
a[3] = 1
a[0] = 2
a = {0:2, 3:1}
python会自动更改我的广告订单。 由于python声称dict是无序的,所以我并不完全 理解为什么python会维护这样的搜索顺序。 python是否通过哈希表实现dict并存储另一个 为索引排序设置?
希望我明白这个问题。
谢谢
答案 0 :(得分:17)
dict的顺序完全取决于对象的散列函数(如果存在散列碰撞,则为插入顺序)。整数哈希自己(至少高达sys.maxint
):
>>> hash(1)
1
(C)python实现获取对象的哈希值,并使用几位来确定表中的索引。它需要多少位取决于字典的长度。默认情况下,dict有8个可用插槽,因此数字0
和8
会发生冲突。我们可以看到如下:
>>> d1 = {}
>>> d1[0] = 'foo'
>>> d1[8] = 'bar'
>>> d1
{0: 'foo', 8: 'bar'}
>>>
>>> d2 = {}
>>> d2[8] = 'bar'
>>> d2[0] = 'foo'
>>> d2
{8: 'bar', 0: 'foo'}
由于0
和8
在我们的字典中发生冲突,因此插入顺序似乎已被维护。 0
占用了第一个可用的广告位(毕竟,无论您从0
获得多少位,您都会获得0
)。 8
也尝试占用该位置。但是,如果采用该槽,则冲突解决将接管并且python会在稍后的某个插槽中插入该值。
当然,如果你的词典恰好有超过5个元素,那么它将被调整大小(我认为是16,但不要引用我)和0
和{{1}将不再碰撞...
8
注意,(已排序)顺序被保留(不是插入顺序),这意味着每个整数都在哈希表中得到它的首选点(没有冲突)。我认为当大约2 / 3rds满时,dict会被调整大小。
请注意,这纯粹是学术性的 - python规范并没有说它是如何工作的,所以它可以随时改变。请不要依赖这种行为。其中大部分可以从旁边的comments in the source code和documentation收集......
答案 1 :(得分:1)
Dict索引排序只是dict如何实现的结果,不应该依赖。
准确地说,Python不会更改您的插入顺序(因为它只是定义为将项目插入到dict中的顺序),但迭代顺序无法保证。
当Python创建一个dict时,它为8个键值对创建了足够的空间(我认为)。对于一个空的字典,它们都没有被填满。每当你将一个项放入一个dict时,Python就会获取一个键的哈希值,而key的哈希值决定了该索引的内容。
如果您确实希望迭代顺序与广告订单顺序相同,请查看ordereddict。