Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will a Python dict literal be evaluated in the order it is written?

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?

like image 466
natevw Avatar asked Jan 26 '15 18:01

natevw


People also ask

Is Python dict values ordered?

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.

Does dict values return in order?

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.

Are Python dict Keys ordered?

Python 3.6 (CPython) As of Python 3.6, for the CPython implementation of Python, dictionaries maintain insertion order by default.

Does dict in Python preserve order?

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.


1 Answers

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.

like image 70
Martijn Pieters Avatar answered Sep 21 '22 12:09

Martijn Pieters