[*]
I like @b4hand’s examples, and indeed I have used in the past ChainMap-like structures (but not ChainMap itself) for the two purposes he mentions: multi-layered configuration overrides, and variable stack/scope emulation.
I’d like to point out two other motivations/advantages/differences of ChainMap
, compared to using a dict-update loop, thus only storing the “final” version”:
-
More information: since a ChainMap structure is “layered”, it supports answering question like: Am I getting the “default” value, or an overridden one? What is the original (“default”) value? At what level did the value get overridden (borrowing @b4hand’s config example: user-config or command-line-overrides)? Using a simple dict, the information needed for answering these questions is already lost.
-
Speed tradeoff: suppose you have
N
layers and at mostM
keys in each, constructing a ChainMap takesO(N)
and each lookupO(N)
worst-case[*], while construction of a dict using an update-loop takesO(NM)
and each lookupO(1)
. This means that if you construct often and only perform a few lookups each time, or ifM
is big, ChainMap’s lazy-construction approach works in your favor.
[*] The analysis in (2) assumes dict-access is O(1)
, when in fact it is O(1)
on average, and O(M)
worst case. See more details here.