关于python:dict.values()是否按顺序返回?

Does dict.values() returns in an ordered sequence?

本问题已经有最佳答案,请猛点这里访问。
1
2
3
4
5
dict_mark = {'Wang': 'C', 'Li': 'B', 'Ma': 'A'}
s = ''
for c in dict_mark.values():
    s += c
print(s)

字典是无序的,所以为什么dict_mark.values()总是像'C' 'B' 'A'那样返回这个值序列?

为什么不是'B' 'A' 'C''A' 'B' 'C'呢?


无序不代表不确定性。

从python 2.x文档:

If items(), keys(), values(), iteritems(), iterkeys(), and
itervalues() are called with no intervening modifications to the
dictionary, the lists will directly correspond.

在python 3.x文档中:

Keys and values are iterated over in an arbitrary order which is non-random, varies across Python implementations, and depends on the dictionary’s history of insertions and deletions.

因此,在修改字典之前,返回的序列总是相同的。您不能对其中排序的对象进行假设。

看看这个问题及其答案,在这里他们讨论了为什么(以及如何)在python 3.6+dict中进行排序。


字典存储为哈希表。在3.6之前的Python版本中,迭代是按照它们出现在哈希表中的顺序进行的,这意味着获得的顺序取决于每个键的哈希值。当出现哈希冲突时,它还可以根据插入和删除的顺序变化。

在python 2.x中,字符串的散列值是一个固定值,因此,尽管它可能在不同的python版本之间发生变化,但对于给定的字典和字典上的一组固定操作,您将始终看到相同的顺序。

在某些版本的python 3中,字符串的散列值具有随机因子,因此不同的运行将产生不同的结果。在python 3.6中,迭代顺序不再依赖于散列键,因此您将再次得到一个与插入顺序相关的固定顺序(但不能保证将来不会再次更改)。

1
2
3
4
5
6
7
8
9
10
$ python2.7 /tmp/t.py
ACB
$ python2.7 /tmp/t.py
ACB
$ python3.5 /tmp/t.py
BCA
$ python3.5 /tmp/t.py
ABC
$ python3.5 /tmp/t.py
CBA


dict将其数据存储在哈希表数据结构中。那么哈希表是如何工作的呢?

简而言之:假设dict被初始化为8槽数组,就像对象一样。当您向dict中添加一个新的键值对时,它会使用一个返回键值所在槽的函数来cx1〔1〕键。这不是确定性的,因为槽可能已经被占用了;所以您需要重新评估并寻找另一个槽。

这就是为什么从dict.values()中检索值的顺序取决于其中的数据。这就是它被称为无序的原因。

例如,考虑这个简单的dict:

1
2
3
4
5
6
7
>>> d = {'a': 1, 'aa': 2}
>>> d
{'a': 1, 'aa': 2}

>>> d = {'aa': 1, 'a': 2}
>>> d
{'aa': 1, 'a': 2}

如果更改键的顺序,则在打印dict key-value对时也会显示不同的顺序。但是看看如果我用不同的钥匙会发生什么

1
2
3
>>> d = {'b': 1, 'a': 2}
>>> d
{'a': 2, 'b': 1}

尽管我先说明了'b'键,但它是在'a'之后分配的。

但是,一旦设置了dict,当调用dict.items()时,它将始终返回相同的顺序。


自python 3.6以来,dict关键字的顺序是:https://mail.python.org/pipermail/python-dev/2016-09/146327.html


这取决于python中的几个方面,dict是如何排序的。你不应该考虑这个问题,因为听写命令并不重要。