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

Viewed 2885
dict_mark = {'Wang': 'C', 'Li': 'B', 'Ma': 'A'}
s = ''
for c in dict_mark.values():
    s += c
print(s)

dictionary is unordered,so why does dict_mark.values() always return this value sequence like 'C' 'B' 'A'?

Why not 'B' 'A' 'C' or 'A' 'B' 'C'?

5 Answers

Unordered dos not mean not deterministic.

From the python 2.x docs:

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

In python 3.x docs:

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.

Thus, the sequence returned is always the same until you modify the dictionary. You just can't make assumptions on the objects being sorted in it.

Have a look at this question and the answers to it where they discuss about why (and how) in python 3.6+ dicts are actually ordered.

dict stores it's data in a hashtable data structure. So how does hashtable works?

On a nutshell: let's say the dict is initalized to 8 slots array-like object. When you add a new key-value pair to the dict, it hashes the key using a function that returns the slot the key will reside. This isn't deterministic since the slot may be already taken; so you need to re-evaluate and look for another slot.

That's why the order you retrieve values from dict.values() changes depend on the data in it. That's why it is called unordered.

For example, consider this simple dict:

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

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

If I change the order of the keys, it also appears different when I print the dict key-value pairs. But look what happens if I use different key

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

Althought I stated the 'b' key first, it was allocated after 'a'.

However, once the dict is set, it will always return the same order when called dict.items().

The dictionary is stored as a hash table. In versions of Python prior to 3.6 iteration is done in the order they appear in the hash table, so that means the order you get depends on the hash value of each key. It also can vary based on the order of insertion and deletion when there have been hash conflicts.

In Python 2.x the hash value for a string is a fixed value, so while it might change between Python versions you will always see the same order for a given dictionary and a fixed set of actions on the dictionary.

In some versions of Python 3, the hash value for a string has random factor, so different runs will give a different result. In Python 3.6 the iteration order no longer depends on the hash key so you will again get a fixed order which will relate to the order of insertion (but there's no guarantee that it won't change again in the future).

$ 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

It depends on several things in python how dict is ordered. You shouldn't think about it, since ordering in dict doesn't matter.

Related