Let's say that I've got a situation like this in Python:
_avg = {'total':0.0, 'count':0} # HACK: side-effects stored here
def procedure(n):
_avg['count'] += 1
_avg['total'] += n
return n
def get_average():
return _avg['total'] / _avg['count']
my_dict = {
'key0': procedure(0),
'key2': procedure(2),
'key1': get_average()
}
assert(my_dict['key1'] == 1.0)
I know that the order of my_dict.keys()
is undefined, but what I'm wondering is whether the initialization via a literal like this is guaranteed to happen in a particular order. Will the value of my_dict['key1']
always be 1.0
as asserted?
A dictionary in Python is a collection of items that stores data as key-value pairs. In Python 3.7 and later versions, dictionaries are sorted by the order of item insertion. In earlier versions, they were unordered.
values() changes depend on the data in it. That's why it is called unordered. 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.
Python 3.6 (CPython) As of Python 3.6, for the CPython implementation of Python, dictionaries maintain insertion order by default.
Since dictionaries in Python 3.5 don't remember the order of their items, you don't know the order in the resulting ordered dictionary until the object is created. From this point on, the order is maintained. Since Python 3.6, functions retain the order of keyword arguments passed in a call.
Dictionary evaluation order should be the same as written, but there is a outstanding bug where values are evaluated before the keys. (The bug was finally fixed in Python 3.5).
Quoting from the reference documentation:
Python evaluates expressions from left to right.
and from the bug report:
Running the following code shows
"2 1 4 3"
, but in reference manual http://docs.python.org/reference/expressions.html#expression-lists the evaluation order described as{expr1: expr2, expr3: expr4}
def f(i): print i return i {f(1):f(2), f(3):f(4)}
and Guido stated:
I am sticking with my opinion from before: the code should be fixed. It doesn't look like assignment to me.
This bug is fixed in Python 3.5, so on Python 3.4 and earlier the values are still evaluated before the keys:
>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=4, micro=2, releaselevel='final', serial=0)
>>> def f(i):
... print(i)
... return i
...
>>> {f(1):f(2), f(3):f(4)}
2
1
4
3
{1: 2, 3: 4}
Since your code doesn't require the keys to be evaluated first, your code is guaranteed to work correctly; key-value pairs are still evaluated in order even if the keys are evaluated after each corresponding value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With