oria general
oria general

Reputation: 273

python dictionary replace dict[] operator with dict.get() behavior

my_dict = {'a': 1}

I wish for my_dict['a'] to behave the same as my_dict.get('a') That way, if I do my_dict['b'], I will not raise an error but get the default None value, the same way you would get it from my_dict.get('b')

In the case of my_dict = {'a': {'b': 2}} I could do my_dict['a']['b'] and it would act as my_dict.get('a').get('b')

When doing my_dict['b'] = 2 it will act same as my_dict.update({'b': 2})

Is it possible to do so that I will not have to inherit from dict?

Upvotes: 0

Views: 64

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1123400

You can use a collections.defaultdict() object to add a new value to the dictionary each time you try to access a non-existing key:

>>> from collections import defaultdict
>>> d = defaultdict(lambda: None)
>>> d['a'] is None
True
>>> d
defaultdict(<function <lambda> at 0x10f463e18>, {'a': None})

If you don't want the key added, create a subclass of dict that implements the __missing__ method:

class DefaultNoneDict(dict):
    def __missing__(self, key):
        return None

This explicitly won't add new keys:

>>> d = DefaultNoneDict()
>>> d['a'] is None
True
>>> d
{}

If you wanted to chain .get() calls, you'll have to return an empty dictionary instead, otherwise dict.get(keyA).get(keyB) will fail with an attribute error (the first None returned won't have a .get() method).

Generally speaking, it is better to stick to the default type and be explicit. There is nothing wrong with:

value = some_d.get(outer, {}).get(inner)

Using a defaultdict or a dict subclass with custom __missing__ hook have a downside: they will always produce a default when the key is missing, even when you accidentally produced incorrect keys somewhere else in your code. I often opt for an explicit dict.get() or dict.setdefault() codepath over defaultdict precisely because I want a non-existing key to produce an error in other parts of my project.

Upvotes: 5

Related Questions