What is the proper way to extract the value from nested dictionary in Python?

Question:

A nested dictionary:

nested_dict = {"fruit": {"apple":{"status": "new", "sold": True},
                         "banana": 10,
                         "watermelon": 30},
               "meat": {"red": 39, "white": 13}}

res = nested_dict.get("fruit", {}).get("apple", {}).get("status")
if res:
    print(f"{res = }")

Is there any better practise to extract the value from the nested dictionary?

Asked By: tung

||

Answers:

I’m not totally sure about speed, but personally I like to reference dictionary elements in the same way you would access the elements of a list, tuple, or most other python data structure, like this for your example:

In [24]: res = nested_dict["fruit"]["apple"]["status"]

In [25]: print(res)
new

I should also note it looks like you’re constructing something known as a JSON file, a common file format which Python has a nice module for, i.e the json module. Might be worth looking into!

Answered By: Jackson Sheppard

The proposal in your question is fine.

If you have a lot of data like this, it maybe worth writting some helper codem to avoid repetition, or install a 3rdy party lib that makes it easier to deal with nested data.

One such library is a project I authored named "extradict" (it can be installed with pip install extradict). It features a NestedData class which may hold nested dictionaries and lists, and allow for item access using the dot notation in the key. So you can get to your data, in this example, by using simply ["fruit.apple.status"]. Here is the full snippet:

In [1]: nested_dict = {"fruit": {"apple":{"status": "new", "sold": True},
   ...:                          "banana": 10,
   ...:                          "watermelon": 30},
   ...:                "meat": {"red": 39, "white": 13}}


In [2]: from extradict import NestedData

In [3]: nested = NestedData(nested_dict)

In [4]: nested.get("fruit.apple.status")
Out[4]: 'new'
In [5]: nested.get("fruit.mango.status")
<None>
In [7]: 

Note however, that in this particular example, you will get an error with extradict.NestedData if you try to get the "status" of a fruit that contains a number, and not another dict, which might contain the status key. Hopefully this is just example data, and you don’t have such heterogeneous data structures around.


In [7]: nested_dict.get("fruit", {}).get("banana", {}).get("status")
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
(...)
AttributeError: 'int' object has no attribute 'get'

In [8]: nested.get("fruit.banana.status")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
(...)
TypeError: 'int' object is not subscriptable

Answered By: jsbueno