Python missing Method in Dictionary Subclasses
The __missing__ method in Python is a special hook
designed for subclasses of the built-in dict (or
collections.UserDict) to manage lookups for nonexistent
keys. When implemented, it intercepts failed key lookups via the bracket
operator (d[key]) and defines fallback behavior—such as
generating default values, automatically caching computed results, or
normalizing lookup keys—before a KeyError is raised. This
article explains how __missing__ operates under the hood,
how standard Python features rely on it, and how to implement it
effectively in your own custom dictionaries.
How __missing__ Works
In standard Python dictionaries, requesting a key that does not exist
using bracket notation raises a KeyError. Internally, the
base dict.__getitem__(self, key) method contains a fallback
mechanism: if the key is not in the dictionary and the subclass defines
a __missing__(self, key) method, Python invokes that
method, passing the missing key as an argument.
Whatever value __missing__ returns becomes the result of
the d[key] expression. If __missing__ raises
an exception (such as KeyError), that exception propagates
outward.
The Foundation of
collections.defaultdict
The most prominent example of __missing__ in Python's
standard library is collections.defaultdict. When an access
fails, defaultdict calls its internal
__missing__ method, which invokes the provided
default_factory callable, inserts the resulting value into
the dictionary under that key, and returns it.
You can replicate this behavior manually in a custom subclass:
class AutoDefaultDict(dict):
def __init__(self, default_factory, *args, **kwargs):
super().__init__(*args, **kwargs)
self.default_factory = default_factory
def __missing__(self, key):
# Generate the value, store it for future lookups, and return it
value = self.default_factory()
self[key] = value
return valueCommon Use Cases
- Auto-Populating Caches: You can build an on-demand cache where requesting a missing key triggers an expensive fetch or calculation, stores the result, and returns it seamlessly.
- Case-Insensitive Lookups: Subclasses can inspect
alternative casings of a string key inside
__missing__to retrieve existing items without modifying the underlying stored keys. - Structured Default Values: Unlike
.get(), which only returns a fallback without persisting it,__missing__allows you to mutate the dictionary dynamically so subsequent reads are instantaneous.
Important Behaviors and Limitations
To use __missing__ correctly, keep the following
operational nuances in mind:
- Only Triggered by
__getitem__: Python only calls__missing__when access occurs through indexing syntax (d[key]). Methods liked.get(key)and thekey in dmembership operator bypass__missing__entirely and will report the key as missing. - Inheritance Requirement: Defining
__missing__directly on an instance of a standarddicthas no effect. It must be defined as a method on a subclass inheriting fromdictorcollections.UserDict. - State Mutation:
__missing__does not automatically store returned values in the dictionary. If you want the generated value to persist, you must explicitly assign it toself[key]within the method body.