__missing__
__missing__(self, key) __missing__ is a dict subtype hook that Python calls automatically when a key lookup fails. It lets you define custom behaviour for d[key] access instead of the default KeyError.
When __missing__ is called
Python calls __missing__ only after dict.__getitem__ has already raised KeyError. This means the hook only applies to classes that inherit directly from dict — not from collections.abc.Mapping.
The lookup chain for d[key]:
dict.__getitem__(d, key)
→ key found? return value
→ key NOT found? raise KeyError
→ Python catches KeyError, calls d.__missing__(key)
→ __missing__ returns a value? that becomes the result of d[key]
→ __missing__ raises KeyError? it propagates
If __getitem__ returns NotImplemented (for cooperative multiple inheritance), Python does not fall back to __missing__.
Basic example
class StrDict(dict):
def __missing__(self, key):
return f"[missing: {key}]"
d = StrDict({"name": "Alice"})
print(d["name"]) # Alice
print(d["age"]) # [missing: age]
The return value of __missing__ becomes the result of the original d[key] expression.
Auto-vivification with nested dicts
A common use case is building nested dicts on demand — the “autovivification” pattern:
class TreeDict(dict):
def __missing__(self, key):
self[key] = TreeDict()
return self[key]
tree = TreeDict()
tree["a"]["b"]["c"] = 42
print(tree["a"]["b"]["c"]) # 42
Without __missing__, accessing tree["a"] on an empty TreeDict would raise KeyError. With it, the nested dict is created and returned silently.
Relationship to collections.defaultdict
collections.defaultdict is implemented using __missing__ internally:
class defaultdict_(dict):
def __init__(self, factory, **kwargs):
super().__init__(**kwargs)
self.default_factory = factory
def __missing__(self, key):
self[key] = self.default_factory()
return self[key]
The key difference: defaultdict calls a factory callable every time a missing key is accessed. With __missing__ you have full control — you can return a static value, compute something, mutate state, or raise an error.
What does NOT trigger __missing__
dict.get(key)— returnsNoneor a default without calling__missing__key in d— uses__contains__, not__getitem__- Subclasses of
collections.abc.Mapping— they use their own__getitem__protocol
Return value and error handling
__missing__ can return any object, including None. If you want the original KeyError to propagate instead of silently returning a default, raise it explicitly:
class StrictDict(dict):
def __missing__(self, key):
raise KeyError(key)
This is useful when you want to log or audit missing key attempts but still treat them as errors.
See Also
__setitem__— controls what happens when you assignd[key] = value__getattr__— general attribute access hook__hash__— required for dict keys, often paired with__eq__