gotchapythonMinorpending
Gotcha: Python dict iteration order is insertion order (but don't rely on it for semantics)
Viewed 0 times
dictorderinsertion-orderOrderedDictequalityJSON
Error Messages
Problem
Python 3.7+ guarantees dict insertion order, but developers sometimes use dicts where ordered data structures (list of tuples, OrderedDict) would be more semantically correct.
Solution
Dict order is guaranteed but semantic intent matters:
# Insertion order IS guaranteed (Python 3.7+):
d = {'c': 3, 'a': 1, 'b': 2}
list(d.keys()) # ['c', 'a', 'b'] - guaranteed
# BUT: equality ignores order:
{'a': 1, 'b': 2} == {'b': 2, 'a': 1} # True!
# Use OrderedDict when order is SEMANTICALLY important:
from collections import OrderedDict
o1 = OrderedDict([('a', 1), ('b', 2)])
o2 = OrderedDict([('b', 2), ('a', 1)])
o1 == o2 # False! Order matters for equality
# When to use what:
# dict: Key-value lookup, order is incidental
# OrderedDict: Order is part of the data's meaning
# list of tuples: Ordered pairs, possibly with duplicate keys
# JSON gotcha: JSON objects have no guaranteed order
# Even though Python dicts are ordered, JSON parsers may not preserve order
import json
json.loads('{"b": 2, "a": 1}') # Order depends on parser
# Sorting a dict:
sorted_d = dict(sorted(d.items())) # By key
sorted_d = dict(sorted(d.items(), key=lambda x: x[1])) # By value
# Insertion order IS guaranteed (Python 3.7+):
d = {'c': 3, 'a': 1, 'b': 2}
list(d.keys()) # ['c', 'a', 'b'] - guaranteed
# BUT: equality ignores order:
{'a': 1, 'b': 2} == {'b': 2, 'a': 1} # True!
# Use OrderedDict when order is SEMANTICALLY important:
from collections import OrderedDict
o1 = OrderedDict([('a', 1), ('b', 2)])
o2 = OrderedDict([('b', 2), ('a', 1)])
o1 == o2 # False! Order matters for equality
# When to use what:
# dict: Key-value lookup, order is incidental
# OrderedDict: Order is part of the data's meaning
# list of tuples: Ordered pairs, possibly with duplicate keys
# JSON gotcha: JSON objects have no guaranteed order
# Even though Python dicts are ordered, JSON parsers may not preserve order
import json
json.loads('{"b": 2, "a": 1}') # Order depends on parser
# Sorting a dict:
sorted_d = dict(sorted(d.items())) # By key
sorted_d = dict(sorted(d.items(), key=lambda x: x[1])) # By value
Why
CPython 3.7+ guarantees insertion order as a language spec. But equality comparison ignores order, which can be surprising.
Revisions (0)
No revisions yet.