python的字典排序有多可靠?

时间:2016-02-06 03:56:40

标签: python dictionary

我需要快速哈希一个字典(一个计数器),我注意到python似乎以相同的顺序使用相同的键来命令字典,即使它们的构造方式不同。事实上,这些词典似乎能够在相当多的滥用中存活下来:

>>> D = {'a': 1, 'b': 2, 'c': 3}
>>> list(D)
['b', 'c', 'a']
>>> list(D)
['b', 'c', 'a']
>>> list(D)
['b', 'c', 'a']
>>> list(D)
['b', 'c', 'a']
>>> E = {'a': 1, 'b': 2, 'c': 3}
>>> list(E)
['b', 'c', 'a']
>>> list(E)
['b', 'c', 'a']
>>> list(E)
['b', 'c', 'a']
>>> F = {'a': 1, 'b': 2, 'c': 3}
>>> list(F)
['b', 'c', 'a']
>>> list(F)
['b', 'c', 'a']
>>> list(F)
['b', 'c', 'a']
>>> list(F)
['b', 'c', 'a']
>>> G = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
>>> list(G)
['b', 'c', 'a', 'd']
>>> list(G)
['b', 'c', 'a', 'd']
>>> list(G)
['b', 'c', 'a', 'd']
>>> list(F)
['b', 'c', 'a']
>>> F.pop('a')
1
>>> list(F)
['b', 'c']
>>> F['a'] = 2
>>> list(F)
['b', 'c', 'a']
>>> list(F)
['b', 'c', 'a']
>>> H = {'b': 2, 'a': 1, 'c': 3}
>>> list(H)
['b', 'c', 'a']
>>> H = {'b': 2, 'c': 1, 'a': 3}
>>> list(H)
['b', 'c', 'a']
>>> K = {'b': 2, 'c': 1, 'a': 3, 'd': 4}
>>> list(K)
['b', 'c', 'a', 'd']
>>> K = {'b': 2, 'c': 1, 'd': 3, 'a': 4}
>>> list(K)
['b', 'c', 'a', 'd']

我的问题是,如果我的词典具有相同的键和相同的值,我是否可以指望键处于相同的顺序,至少在运行的python实例的生命周期中? 请注意,我知道python在决定如何订购字典方面有点难以理解,但我想知道如果给出相同的输入,同一个python实例每次都会返回相同的键排序。

4 个答案:

答案 0 :(得分:2)

不订购常规python dicts。永远不能保证当你获得密钥列表时,它们将是你期望的顺序。

如果您想保留订单,请使用有序的字典。

https://docs.python.org/2/library/collections.html#collections.OrderedDict

答案 1 :(得分:1)

  

如果我的词典具有相同的键和相同的值,我可以指望键处于相同的顺序

没有

>>> list({'d': 0, 'l': 0})
['d', 'l']

>>> list({'l': 0, 'd': 0})
['l', 'd']

答案 2 :(得分:1)

就语言定义而言,不能不依赖于稳定排序,因为它不是在语言定义中承诺的。

现在,可能在短期和中期你会发现这种排序是稳定的,这是有道理的:计算机是确定性的,所以从实验的一次迭代中得到相同的结果是合理的。下一个。 (但是,由于它们是复杂的系统,这种不确定的机器可能仍会产生意想不到的结果,因为你不知道决定因素的因素)但是,这种推理并没有延伸到长期,这就是你应该编程的to,因为语言实现可以自由选择任何方式来订购它喜欢的那些键,并且只要实现与语言定义一致,就可以随时更改该选择。这意味着,如果在不同的实现下运行,依赖于某些保持稳定的顺序的程序会受到破坏,并且在更新实现时它们会受到破坏。 这不是你想要的地方,因此你不应该对字典键的排序稳定性做任何假设。

话虽这么说,如果你只是关注稳定性只是在一个正在运行的python实例的生命周期那么这似乎是一个安全的赌博 - 再次,计算机是确定性 - 但仍然是一场赌博。仔细测试比你期望遇到的更复杂的病例,然后决定那块砧板是否适合放松你的脖子。

答案 3 :(得分:1)

鉴于没有人提到这一点,我会告诉你哈希随机化是enabled by default since Python 3.3

使用散列随机化,hash('abc')的结果在每次Python运行之间是不同的。因为散列位于字典的基础(它们用于确定dict使用的内部数组中项的位置),所以对排序的保证更少。

$ python3.5
>>> d = {'a': 1, 'b': 2, 'c': 3}
>>> list(d)
['a', 'c', 'b']
>>> list(d)
['a', 'c', 'b']

$ python3.5
# new process, new random seed, new ordering
>>> d = {'a': 1, 'b': 2, 'c': 3}
>>> list(d)
['c', 'a', 'b']
>>> list(d)
['c', 'a', 'b']