DEV Community

Kelvin Wangonya
Kelvin Wangonya

Posted on • Originally published at wangonya.com

3 2

Handling missing dict keys

Trying to access a non-existent key using this notation raises a KeyError: dict[key]. An easy workaround for this is to use get(key) instead, which returns None if key isn't found, or get(key, default) which returns default if key isn't found.

>>> d = {}
>>> d
{}
>>> d["x"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'x'
>>> d.get("x")
>>> d
{}
>>> d.get("x","y")
'y'
>>> d
{}
>>>
Enter fullscreen mode Exit fullscreen mode

But what if you want to not only return a default if the key is missing, but also assign that default to the specified key in the dict? There are a couple of ways to do that.

1. setdefault

setdefault(key[, default])

If key is in the dictionary, return its value. If not, insert key with a value of default and return default. default defaults to None.

docs

>>> d
{}
>>> d.setdefault("x","y")
'y'
>>> d
{'x': 'y'}
>>>
Enter fullscreen mode Exit fullscreen mode

2. defaultdict

class collections.defaultdict(default_factory=None, /[, ...])

The first argument provides the initial value for the default_factory attribute; it defaults to None. All remaining arguments are treated the same as if they were passed to the dict constructor, including keyword arguments.

docs

>>> from collections import defaultdict
>>> i = defaultdict(int)
>>> i
defaultdict(<class 'int'>, {})
>>> i["x"]
0
>>> i
defaultdict(<class 'int'>, {'x': 0})
>>> i["y"]
0
>>> i
defaultdict(<class 'int'>, {'x': 0, 'y': 0})
>>>
Enter fullscreen mode Exit fullscreen mode

Note that no KeyError is raised despite the key not existing at first. Instead, the key is created with the default value of the type passed into defaultdict, in this case 0 for int. If we used list instead, the default value would be [], an so on.

Further reading:

3. Implement __missing__

This is actually what defaultdict does behind the scenes. Use this when defaultdict doesn't fit your usecase.

>>> class M(dict):
...     def __missing__(self, key):
...             value = "my default value"
...             self[key] = value
...             return value
...
>>>
>>> m = M()
>>> m
{}
>>> m["x"]
'my default value'
>>> m
{'x': 'my default value'}
>>> m["y"]
'my default value'
>>> m
{'x': 'my default value', 'y': 'my default value'}
>>>
Enter fullscreen mode Exit fullscreen mode

Image of Datadog

The Essential Toolkit for Front-end Developers

Take a user-centric approach to front-end monitoring that evolves alongside increasingly complex frameworks and single-page applications.

Get The Kit

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

AWS GenAI LIVE!

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️