3
votes

I'm reading @Martijn Pieters' response to Converting dict to OrderedDict. The main point of his answer is that passing a regular dict to OrderedDict() will not retain the order as desired, because the dict that you are passing has already "lost" any semblance of order. His solution is to pass tuples that make up the dict's key/value pairs instead.

However, I also noticed the following in the docs:

Changed in version 3.6: With the acceptance of PEP 468, order is retained for keyword arguments passed to the OrderedDict

Does this invalidate the issue that Martijn points out (can you now pass a dict to OrderedDict), or am I misinterpreting?

from collections import OrderedDict

ship = {'NAME': 'Albatross',
         'HP':50,
         'BLASTERS':13,
         'THRUSTERS':18,
         'PRICE':250}
print(ship) # order lost as expected
{'BLASTERS': 13, 'HP': 50, 'NAME': 'Albatross', 'PRICE': 250, 'THRUSTERS': 18}
print(OrderedDict(ship)) # order preserved even though a dict is passed?
OrderedDict([('NAME', 'Albatross'),
             ('HP', 50),
             ('BLASTERS', 13),
             ('THRUSTERS', 18),
             ('PRICE', 250)])

I get this same (correct) order if I run a for key in ... loop over the OrderedDict as well, seeming to imply it's OK to pass the dict itself.

Edit: this was also contributing a bit to my confusion: Are dictionaries ordered in Python 3.6+?

1
Order is retained for keyword arguments passed to the OrderedDict. Not sure where you are getting the idea you have from.Jared Smith

1 Answers

7
votes

Order is retained for keyword arguments passed to the OrderedDict

What this means is that the following is guaranteed to preserve the order:

od = OrderedDict(a=20, b=30, c=40, d=50)

that is, the order in which the keyword arguments are passed is retained in **kwargs. This, in Python 3.6, is a language feature; all other implementations need to follow suit.

How this works is, in order for this call to be performed, a dictionary is created that holds the keyword arguments. Being a dict, prior to 3.6, it lost information about the order in which these were supplied.

With PEP 468 getting accepted in 3.6, this is guaranteed to now use an ordered mapping that holds on to this information (in CPython, the "ordered mapping" happens to be a dict but, that's an implementation detail -- Update: A language feature as of Python 3.7.).


Using OrderedDict(ship), as you currently do, also preserves the order in 3.6 because dict has that implementation now, not due to PEP 468. This is something you shouldn't depend on as it is considered an implementation detail of the CPython implementation; in the future this might change (and it looks like it will) but, until then, you shouldn't depend on it.

As of Python 3.7, the previous is now guaranteed to preserve the order across implementations as dict insertion order is now a language feature.