ChainMap pop / popitem / clear

A key that is visible through the ChainMap may still be impossible to delete through it: if it lives in a later mapping, pop and del raise KeyError("Key not found in the first mapping: …").

ChainMap methodsPython 3.3+Live demo
Common call
cm.pop('key') · cm.popitem() · cm.clear()
Returns
value · (key, value) · None
Replaces
cm.maps[0].pop(...) — which is what they call
Watch out
a key only in a later map cannot be popped
ChainMap.pop(key[, default])
→ value | tuple | None

Demo

Live evaluation
pop only looks in the first mapping.
Try:
Inputs
alist[str]keys of maps[0] (value 1)
blist[str]keys of maps[1] (value 2)
keystrkey to pop
Code
from collections import ChainMap
cm = ChainMap(dict.fromkeys(['x', 'y'], 1), dict.fromkeys(['y', 'z'], 2))
(cm.pop('y'), cm)
Result
(1, ChainMap({'x': 1}, {'y': 2, 'z': 2}))

Popping y removes it from maps[0], after which the y in maps[1] shows through again. Popping z, which only exists in maps[1], raises KeyError: "Key not found in the first mapping: 'z'". After clear() the chain still exposes the keys of the second mapping.

Parameters

NameTypeRequiredDescription
keyhashableyespop: the key to remove from maps[0].
defaultobjectnopop: returned instead of raising when maps[0] lacks the key.

Return value

value | tuple | None — pop → the removed value; popitem → a (key, value) pair; clear → None.

Common patterns

Remove a local override
Revert to the lower layer by deleting from maps[0].
settings.pop('color', None)
Delete from a specific layer
Go through .maps.
del cm.maps[1]['color']

Examples

1. pop from maps[0]
from collections import ChainMap cm = ChainMap({'a': 1}, {'a': 2}) (cm.pop('a'), cm['a'])
Returns
(1, 2)
2. pop with a default
from collections import ChainMap ChainMap({}, {'a': 2}).pop('a', 'none')
Returns
'none'
3. A key in a later map cannot be popped
from collections import ChainMap ChainMap({}, {'a': 2}).pop('a')
Returns
KeyError: "Key not found in the first mapping: 'a'"
4. del follows the same rule
from collections import ChainMap cm = ChainMap({}, {'a': 2}) del cm['a']
Returns
KeyError: "Key not found in the first mapping: 'a'"
5. popitem
from collections import ChainMap ChainMap({'a': 1, 'b': 2}, {'c': 3}).popitem()
Returns
('b', 2)
6. popitem with an empty maps[0]
from collections import ChainMap ChainMap({}, {'c': 3}).popitem()
Returns
KeyError: 'No keys found in the first mapping.'
7. clear only empties maps[0]
from collections import ChainMap cm = ChainMap({'a': 1}, {'b': 2}) cm.clear() cm
Returns
ChainMap({}, {'b': 2})

Pitfalls

1. Deleting a key you can see
"key in cm" is True for keys in any mapping, but deletion needs the key in maps[0].
check with in
from collections import ChainMap
cm = ChainMap({}, {'a': 1})
if 'a' in cm:
    del cm['a']
KeyError: "Key not found in the first mapping: 'a'"
check maps[0]
from collections import ChainMap
cm = ChainMap({}, {'a': 1})
if 'a' in cm.maps[0]:
    del cm['a']
cm
ChainMap({}, {'a': 1})
2. Expecting clear() to empty the chain
Lower mappings are untouched. Clear each one via .maps if that is what you want.
cm.clear()
from collections import ChainMap
cm = ChainMap({'a': 1}, {'b': 2})
cm.clear()
len(cm)
1
clear every map
from collections import ChainMap
cm = ChainMap({'a': 1}, {'b': 2})
for m in cm.maps:
    m.clear()
len(cm)
0

When to use

Use it
  • Removing local overrides so defaults show through again
Reach for something else
  • Removing a key everywhere → loop over cm.maps

Notes

CPython impl
Each wraps the same call on self.maps[0] and re-raises KeyError with a ChainMap-specific message
Errors
pop/del: KeyError('Key not found in the first mapping: <repr>'); popitem: KeyError('No keys found in the first mapping.')

FAQ

Deletion (pop, del, popitem) only works on the first mapping. The key you are removing exists only in a later mapping, which ChainMap never modifies.