A Warning About Sorting Dictionaries and Python Versions
I recently had to write some Python code to sort a dictionary. One of the common ways to do that in Python 3 is to use a dictionary comprehension and the sorted() method. For example, to sort a dictionary by its keys:
dict = {'turnip': 2, 'potato': 3, 'carrot': 1}
sort_by_key = {k: v for k, v in sorted(
dict.items(),
key = lambda item: item[0]
)}
print(sort_by_key)
The output of this should be:
{'carrot': 1, 'potato': 3, 'turnip': 2}
However, that is not the result I was getting. Rather, sort_by_key
in my case was not sorted at all:
{'turnip': 2, 'potato': 3, 'carrot': 1}
And that was strange because I could have sworn this kind of code had worked before. Granted, it was on a completely different computer where it had worked. But it was not working on my present computer.
I did some research. A lot of sources on the Internet stated that the above should work for sorting a dictionary. Even this source said the same. Except that it mentioned something important: in Python 3.6, dictionaries are ordered. Python 3.6.
I checked which version I had on my system. It was Python 3.5.
That is why it was not working.
It turns out that the expression sorted(dict.items(), key = lambda item: item[0])
was, in fact, producing a properly sorted list of tuples:
[('carrot', 1), ('potato', 3), ('turnip', 2)]
But the dictionary comprehension — the k: v for k, v in ...
part — that was inserting those tuples into a new dictionary was doing so into a dictionary that did not maintain insertion ordering. And that is because dictionaries in Python 3.5 and lower do not maintain such ordering.
I dug deeper, and this article summarized the timeline of the changes to ordering in Python dictionaries. It turns out that while dictionaries maintained insertion ordering starting in 3.6, according to the release notes it was only an implementation detail and was not something one should rely on in future versions. However, it actually became official in Python 3.7, according to its release notes. Thus, you could depend on the above technique working in Python 3.7, although it would also work in Python 3.6.
So just remember: the default dictionary implementation in Python 3.6 and above maintains insertion ordering, whereas in Python 3.5 and below you would need to use something like an OrderedDict
to maintain insertion ordering.