I'm referring to the OrderedDict from the collections
module, which is an ordered dictionary.
If it has the added functionality of being orderable, which I realize may often not be necessary but even so, are there any downsides? Is it slower? Is it missing any functionality? I didn't see any missing methods.
In short, why shouldn't I always use this instead of a normal dictionary?
No it won't become redundant in Python 3.7 because OrderedDict is not just a dict that retains insertion order, it also offers an order dependent method, OrderedDict. move_to_end() , and supports reversed() iteration*.
Intent signaling: If you use OrderedDict over dict , then your code makes it clear that the order of items in the dictionary is important. You're clearly communicating that your code needs or relies on the order of items in the underlying dictionary.
OrderedDict is over 80% slower than the standard Python dictionary (8.6/4.7≈1.83).
How are ordered dictionaries (OrderedDict) different from a normal dictionary? OrderedDict maintains the insertion order of keys while a normal dictionary does not.
OrderedDict
is a subclass of dict
, and needs more memory to keep track of the order in which keys are added. This isn't trivial. The implementation adds a second dict
under the covers, and a doubly-linked list of all the keys (that's the part that remembers the order), and a bunch of weakref proxies. It's not a lot slower, but at least doubles the memory over using a plain dict
.
But if it's appropriate, use it! That's why it's there :-)
The base dict is just an ordinary dict mapping keys to values - it's not "ordered" at all. When a <key, value>
pair is added, the key
is appended to a list. The list is the part that remembers the order.
But if this were a Python list, deleting a key would take O(n)
time twice over: O(n)
time to find the key in the list, and O(n)
time to remove the key from the list.
So it's a doubly-linked list instead. That makes deleting a key constant (O(1)
) time. But we still need to find the doubly-linked list node belonging to the key. To make that operation O(1)
time too, a second - hidden - dict maps keys to nodes in the doubly-linked list.
So adding a new <key, value>
pair requires adding the pair to the base dict, creating a new doubly-linked list node to hold the key, appending that new node to the doubly-linked list, and mapping the key to that new node in the hidden dict. A bit over twice as much work, but still O(1)
(expected case) time overall.
Similarly, deleting a key that's present is also a bit over twice as much work but O(1)
expected time overall: use the hidden dict to find the key's doubly-linked list node, delete that node from the list, and remove the key from both dicts.
Etc. It's quite efficient.
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