Safely indexing dictionary tree

Viewed 51

The below code just works fine for my simple case, but is there any generic and pythonic way?

In [1]: def safe_get(d, *args):
   ...:     n = len(args)
   ...:     if n == 1:
   ...:         return d.get(args[0], '')
   ...:     if n == 2:
   ...:         return d.get(args[0], {}).get(args[1], '')
   ...:     if n == 3:
   ...:         return d.get(args[0], {}).get(args[1], {}).get(args[2], '')
   ...:         

In [2]: d = {
   ...:     'name': {
   ...:         'title': 'Name',
   ...:         'value': 'Me',
   ...:         'meta': {'sal': 'Mr.', 'gender': 'm'}
   ...:     }
   ...: }

In [3]: safe_get(d, 'name', 'value')
Out[3]: 'Me'

P.S.: I am a pharmacist, not a programmer.

2 Answers

The following should work:

def safe_get(d, *args):
    for arg in args:
        d = d.get(arg, {})
    return "" if d == {} else d

d = {'a': {'b': {'c': 100}}}
safe_get(d, 'a', 'b', 'c')
#100

I am not sure what output you are expecting but this seems to solve the problem:

def safe_get(d, *args):

    # If we have only one argument
    if len(args) == 1:
        # And 'd' is a dictionary
        if type(d) == dict:
            return d.get(args[0], "")

        # Otherwise, we have a key that doesn't exist
        return ""

    # If we have multiple arguments, we take the result of the
    # first argument, remove the first argument from 'args' (You
    # may say that it is "consumed"). And, we pass the remnants
    # to the same function until we are left with only one item
    # in "args".
    return safe_get(d.get(args[0], {}), *args[1:])


t_dict = {  # A sample dictionary for testing
    "a": "some_string",
    "b": {
        "c": "another",
        "d": {
            "e": "more strings",
            "f": "even more"
        }
    }
}

print(safe_get(t_dict, "a"))
print(safe_get(t_dict, "b", "d", "e"))
print(safe_get(t_dict, "b", "g"))

Running the above program gives the following output:

jalaj@jalaj:~$ python3 test.py
some_string
more strings

Note that the empty line in the output denotes that the function returned empty string ("").

Related