collections.OrderedDict
Both dict and OrderedDict remember insertion order today. What OrderedDict still adds: reordering (move_to_end), removing from the FRONT (popitem(last=False)), and == that fails when the order differs.
Common call
OrderedDict(a=1, b=2)
Returns
OrderedDict({'a': 1, 'b': 2})
Replaces
dict when you need to reorder or evict the oldest key
Watch out
OrderedDict == dict ignores order; OrderedDict == OrderedDict does not
collections.OrderedDict([items])
→ OrderedDict
Demo
Live evaluation
Same keys, different order: which comparisons notice?
Try:
Inputs
xlist[str]keys of a
ylist[str]keys of b
Code
from collections import OrderedDict a = OrderedDict.fromkeys(['a', 'b']) b = OrderedDict.fromkeys(['b', 'a']) (a == b, dict(a) == dict(b), a == dict(b))
Result
(False, True, True)
For swapped keys, two OrderedDicts compare unequal, while the same data as plain dicts — or an OrderedDict against a dict — compares equal. In the LRU tab, re-reading "a" moves it to the end, so when "d" arrives the oldest entry is "b", and "b" is evicted.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| items | mapping | iterable of pairs | no | Initial content, like dict(): a mapping, (key, value) pairs or keyword arguments — kept in the order given. |
Return value
OrderedDict — A new ordered dictionary; arguments are the same as for dict().
Common patterns
LRU cache
move_to_end on every access, popitem(last=False) to evict.
from collections import OrderedDict cache = OrderedDict() def get(key): cache.move_to_end(key) return cache[key]
Order-sensitive comparison with plain dicts
The docs recipe: compare items and order.
same = p == q and all(k1 == k2 for k1, k2 in zip(p, q))
Pop the oldest key from a plain dict
dict.popitem() always takes the newest; this takes the oldest.
k = next(iter(d)) v = d.pop(k)
Examples
1. Order-sensitive equality
from collections import OrderedDict
OrderedDict(a=1, b=2) == OrderedDict(b=2, a=1)
Returns
False2. Plain dicts ignore order
{'a': 1, 'b': 2} == {'b': 2, 'a': 1}
Returns
True3. Against a dict, order is ignored
from collections import OrderedDict
OrderedDict(a=1, b=2) == {'b': 2, 'a': 1}
Returns
True4. repr
from collections import OrderedDict
OrderedDict([('x', 1), ('y', 2)])
Returns
OrderedDict({'x': 1, 'y': 2})5. Empty repr
from collections import OrderedDict
OrderedDict()
Returns
OrderedDict()6. It is a dict
from collections import OrderedDict
isinstance(OrderedDict(), dict)
Returns
True7. Reorder a key
from collections import OrderedDict
od = OrderedDict.fromkeys('abc')
od.move_to_end('a')
''.join(od)
Returns
'bca'Pitfalls
1. Using OrderedDict just to keep order
Since Python 3.7 a plain dict keeps insertion order. Reach for OrderedDict only for its extra methods or order-sensitive equality.
OrderedDict for order
from collections import OrderedDict list(OrderedDict([('b', 1), ('a', 2)]))
['b', 'a']
a dict does it
list({'b': 1, 'a': 2})
['b', 'a']
2. Calling move_to_end on a plain dict
Only OrderedDict has it. With a dict, pop and re-insert.
dict.move_to_end
d = {'a': 1, 'b': 2} d.move_to_end('a')
AttributeError: 'dict' object has no attribute 'move_to_end'
d[k] = d.pop(k)
d = {'a': 1, 'b': 2} d['a'] = d.pop('a') list(d)
['b', 'a']
When to use
Use it
- LRU caches and other "recently used" ordering
- Queues keyed by name where you pop the oldest entry
- Comparisons where order is part of the value
Reach for something else
- Only needing insertion order → dict (smaller and faster)
- A ready-made LRU cache for a function → functools.lru_cache
Notes
CPython impl
Lib/collections/__init__.py has a pure-Python version, but the C implementation in Objects/odictobject.c is used
vs dict
dict keeps insertion order since 3.7; OrderedDict adds move_to_end, popitem(last=), reversible views since 3.5, and order-sensitive == between OrderedDicts
Versions
Added in 3.1; move_to_end in 3.2 (docs.python.org)
FAQ
Not for keeping order — dict does that. It is still useful for move_to_end(), popitem(last=False), and equality that takes order into account, for example in LRU caches.