I know dictionaries themselves in Python do not have order. However, I'm rather curious if when you call str()
on a dictionary if it is always in the same order. It appears to be sorted (by key), no matter which order I add items:
d={}
d[5]=5
d[1]=1
d["z"]="z"
d["a"]="a"
s=str(d)
print(s)
I know a lot of people will be tempted to say it's not sorted, but please try to prove me wrong by getting unsorted results.
So, are dictionaries converted to strings sorted, by default, in Python 3.4?
Note: Python 3.6 introduces a new, order-preserving implementation of dict
, which makes the following obsolete from 3.6 onwards.
Here are three iterations of your example in three different Python 3.4 interpreter sessions:
Python 3.4.1 (default, Aug 8 2014, 15:05:42)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> d={}
>>> d[5]=5
>>> d[1]=1
>>> d["z"]="z"
>>> d["a"]="a"
>>> s=str(d)
>>> print(s)
{1: 1, 'z': 'z', 'a': 'a', 5: 5}
Python 3.4.1 (default, Aug 8 2014, 15:05:42)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> d={}
>>> d[5]=5
>>> d[1]=1
>>> d["z"]="z"
>>> d["a"]="a"
>>> s=str(d)
>>> print(s)
{1: 1, 'a': 'a', 5: 5, 'z': 'z'}
Python 3.4.1 (default, Aug 8 2014, 15:05:42)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> d={}
>>> d[5]=5
>>> d[1]=1
>>> d["z"]="z"
>>> d["a"]="a"
>>> s=str(d)
>>> print(s)
{1: 1, 5: 5, 'z': 'z', 'a': 'a'}
So, no, the string representation is not sorted, or even in the same order across invocations of the interpreter. In versions of Python up to and including 3.2, the order of dictionaries (and their string representations) was arbitrary but consistent - however, this changed in Python 3.3 as a result of a security fix:
By default, the __hash__()
values of str, bytes and datetime objects are “salted” with an unpredictable random value. Although they remain constant within an individual Python process, they are not predictable between repeated invocations of Python.
This is intended to provide protection against a denial-of-service caused by carefully-chosen inputs that exploit the worst case performance of a dict insertion, O(n^2) complexity. See http://www.ocert.org/advisories/ocert-2011-003.html for details.
Changing hash values affects the iteration order of dicts, sets and other mappings. Python has never made guarantees about this ordering (and it typically varies between 32-bit and 64-bit builds).