Python OrderedDict iteration

neil.millikin picture neil.millikin · May 14, 2013 · Viewed 41k times · Source

Why does my python OrderedDict get initialized 'out of order'?

The solution here is less intriguing than the explanation. There's something here I just don't get, and perhaps an expanation would help others as well as me.

>>> from collections import OrderedDict

>>> spam = OrderedDict(s = (1, 2), p = (3, 4), a = (5, 6), m = (7, 8))

>>> spam
OrderedDict([('a', (5, 6)), ('p', (3, 4)), ('s', (1, 2)), ('m', (7, 8))])

>>> for key in spam.keys():
...    print key    
...
#  this is 'ordered' but not the order I wanted....
a
p
s
m

# I was expecting (and wanting):
s
p
a
m

Answer

Chris Krycho picture Chris Krycho · May 15, 2013

From the docs:

The OrderedDict constructor and update() method both accept keyword arguments, but their order is lost because Python’s function call semantics pass-in keyword arguments using a regular unordered dictionary.

So initialization loses the ordering, because it's basically calling a constructor with **kwargs.

Edit: In terms of a solution (not just an explanation)—as pointed out in a comment by the OP, passing in a single list of tuples will work:

>>> from collections import OrderedDict
>>> spam = OrderedDict([('s',(1,2)),('p',(3,4)),('a',(5,6)),('m',(7,8))])
>>> for key in spam:
...     print(key)
...
s
p
a
m
>>> for key in spam.keys():
...     print(key)
...
s
p
a
m

This is because it's only getting a single argument, a list.