9

Currently I am using the following method, assume dictionary

data[a][b][c]

I use:

if "a" in data and "b" in data["a"] and "c" in data["a"]["b"]:
  ...

Are there any better way?

Ryan
  • 10,041
  • 27
  • 91
  • 156

4 Answers4

8

You can wrap it in a try/except block

try:
    x = data[a][b][c]
    ...do stuff in your "if" clause
except KeyError:
    ...do stuff in your "else" clause
tdelaney
  • 73,364
  • 6
  • 83
  • 116
7

I would typically use the pattern

foo = data.get("a",{}).get("b",{}).get("c",False)
if foo:
...

This requires that the nesting is always the same depth and that data["a"]["b"]["c"] is not "falsy".

colcarroll
  • 3,632
  • 17
  • 25
3

If you need to do this multi-level lookup very often, this helper method can be useful:

def multi_get(dict_obj, *attrs, default=None):
    result = dict_obj
    for attr in attrs:
        if attr not in result:
            return default
        result = result[attr]
    return result

To use it, just call it like:

x = multi_get(data, 'a', 'b', 'c', default=False)
Martín De la Fuente
  • 6,155
  • 4
  • 27
  • 28
  • Maybe change the if to the following one. Then the function can be used to iterate through json-like data structures that include lists as well: if (attr in result) or (isinstance(result, list) and isinstance(attr, int) and (attr < len(result))): It checks if the current iteration of result is a list and the attribute an int and whether the list has enough elements. If yes the element can be accessed using the squre brackets syntax as well. – Pinolpier Jul 12 '22 at 08:38
1

There's two solutions:

Return a default value with defaultdict

You can use a defaultdict, and intstantiate an inner level with another defaultdict. Then, if the key is missing, it'll return an empty dict without throwing errors:

from collections import defaultdict

>>> d = defaultdict(lambda: defaultdict(dict))
>>> d['a']['b']
{}

If you need more levels, you just have to chain many lambda.

Partial reference: Multiple levels of 'collection.defaultdict' in Python

Handle the missing key with a try/except

Another way is to surronding the dict access with try/except block and manage the missing key through the KeyError exception (stop the program, return a default value, etc.)

try:
    x = data[a][b][c]
    # same code of your if statement
except KeyError:
    # stuff you do in your else
Community
  • 1
  • 1
Maxime Lorant
  • 34,607
  • 19
  • 87
  • 97