Python safe method to get value of nested dictionary

I have a nested dictionary. Is there only one way to get values out safely?

    try:
        example_dict['key1']['key2']
    except KeyError:
        pass

Or maybe python has a method like get() for nested dictionary ?

You could use get twice:

    example_dict.get('key1', {}).get('key2')

This will return None if either key1 or key2 does not exist.

Note that this could still raise an AttributeError if example_dict['key1'] exists but is not a dict (or a dict-like object with a get method). The try..except code you posted would raise a TypeError instead if example_dict['key1'] is unsubscriptable.

Another difference is that the try...except short-circuits immediately after the first missing key. The chain of get calls does not.

If you wish to preserve the syntax, example_dict['key1']['key2'] but do not want it to ever raise KeyErrors, then you could use the Hasher recipe:

    class Hasher(dict):
        # https://stackoverflow.com/a/3405143/190597
        def __missing__(self, key):
            value = self[key] = type(self)()
            return value

    example_dict = Hasher()
    print(example_dict['key1'])
    # {}
    print(example_dict['key1']['key2'])
    # {}
    print(type(example_dict['key1']['key2']))
    # <class '__main__.Hasher'>

Note that this returns an empty Hasher when a key is missing.

Since Hasher is a subclass of dict you can use a Hasher in much the same way you could use a dict. All the same methods and syntax is available, Hashers just treat missing keys differently.

You can convert a regular dict into a Hasher like this:

    hasher = Hasher(example_dict)

and convert a Hasher to a regular dict just as easily:

    regular_dict = dict(hasher)

Another alternative is to hide the ugliness in a helper function:

    def safeget(dct, *keys):
        for key in keys:
            try:
                dct = dct[key]
            except KeyError:
                return None
        return dct

So the rest of your code can stay relatively readable:

    safeget(example_dict, 'key1', 'key2')

From: stackoverflow.com/q/25833613

Back to homepage or read more recommendations: