dict
keeps insertion order since Python 3.6 (see this).
OrderedDict
was developed just for this purpose (before Python 3.6).
Since Python 3.6, is the key order always the same for dict
or OrderedDict
?
I wonder whether I can do this in my code and have always the same behavior (except of equality, and some extended methods in OrderedDict
) but more efficiently:
if sys.version_info[:2] >= (3, 6):
OrderedDict = dict
else:
from collections import OrderedDict
Or phrased differently, for Python >=3.6, is there any reason to use OrderedDict
?
The OrderedDict is a subclass of dict object in Python. The only difference between OrderedDict and dict is that, in OrderedDict, it maintains the orders of keys as inserted. In the dict, the ordering may or may not be happen. The OrderedDict is a standard library class, which is located in the collections module.
No, there is no guaranteed order for the list of keys returned by the keys() function. In most cases, the key list is returned in the same order as the insertion, however, that behavior is NOT guaranteed and should not be depended on by your program.
The dictionary implementation doesn't guarantee any specific order. You have probably seen that the order of keys when accessing . keys() is neither the order in which you put those keys into the dictionary, nor is it alphabetical.
As of Python version 3.7, dictionaries are ordered. In Python 3.6 and earlier, dictionaries are unordered. When we say that dictionaries are ordered, it means that the items have a defined order, and that order will not change.
Both OrderedDict
and dict
are insertion-ordered¹ for iteration. There is practically no reason to use OrderedDict
if iteration order is the only deciding point, especially if re-ordering is not needed.
Obviously, if comparison order is desired OrderedDict
and dict
are not interchangeable.
Or phrased differently, for Python >=3.6, is there any reason to use
OrderedDict
?
These days OrderedDict
is to dict
what deque
is to list
, basically. OrderedDict
/deque
are based on linked lists² whereas dict
/list
are based on arrays. The former have better pop/move/FIFO semantics, since items can be removed from the start/middle without moving other items.
Since arrays are generally very cache friendly, the linked list advantage only comes into play for very large containers. Also, OrderedDict
(unlike deque
) does not have guarantees for its linked list semantics and its advantage may thus not be portable. OrderedDict
should primarily be used if many pop/move/FIFO operations are needed and benchmarking can compare the performance of dict
vs. OrderedDict
in practice.
¹This applies to all currently supported implementations compliant with the Python language spec, i.e. CPython and PyPy since Python 3.6.
²OrderedDict
in CPython still preserves O(1) key access. This is realised by also having a "regular" lookup table, using the linked list for order between items and the lookup table for direct item access. It's complicated.
I realize that the different behavior of equality (__eq__
) can be actually a major concern, why such code snippet is probably not good.
However, you could maybe still do this:
if sys.version_info[:2] >= (3, 6):
OrderedDict = dict
else:
from collections import OrderedDict as _OrderedDict
class OrderedDict(_OrderedDict):
__eq__ = dict.__eq__
__ne__ = dict.__ne__
The difference is that with the original collections.OrderedDict
, {1:1,2:2}
is not the same as {2:2,1:1}
, but for dict
and my overwritten OrderedDict
in this example, it is the same.
Some behaviour remains the same, but OrderedDict are reversible and dict are not:
from collections import OrderedDict
d = { "a" : 1, "c" : 2}
od = OrderedDict(d.items())
print(list(reversed(od)))
print(list(reversed(d)))
Output
['c', 'a']
Traceback (most recent call last):
File "path/to/file", line 8, in <module>
print(list(reversed(d)))
TypeError: 'dict' object is not reversible
From the documentation:
In addition to the usual mapping methods, ordered dictionaries also support reverse iteration using reversed().
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