Personally I'd use a list of tuples for that. data = [('Ben',21), ('Jerry', 22)] Or perhaps namedtuples or dataclasses. But if you like the dictionaries that's fine too. There's no best here, it's just whatever you find is the easiest to work with. Answer from socal_nerdtastic on reddit.com
🌐
GeeksforGeeks
geeksforgeeks.org › python › python-nested-dictionary
Python Nested Dictionary - GeeksforGeeks
July 12, 2025 - This example creates a nested dictionary to store details of multiple students. Each student is added as a key and their information (name, age, grade) is stored in an inner dictionary. Python ·
🌐
W3Schools
w3schools.com › PYTHON › python_dictionaries_nested.asp
Python - Nested Dictionaries
Python Examples Python Compiler Python Exercises Python Quiz Python Challenges Python Practice Problems Python Server Python Syllabus Python Study Plan Python Interview Q&A Python Bootcamp Python Training ... A dictionary can contain dictionaries, ...
Discussions

Multiple dictionaries versus nested dictionary?
Personally I'd use a list of tuples for that. data = [('Ben',21), ('Jerry', 22)] Or perhaps namedtuples or dataclasses. But if you like the dictionaries that's fine too. There's no best here, it's just whatever you find is the easiest to work with. More on reddit.com
🌐 r/learnpython
8
2
June 7, 2022
How do you create nested dict in Python? - Stack Overflow
I have 2 CSV files: 'Data' and 'Mapping': 'Mapping' file has 4 columns: Device_Name, GDN, Device_Type, and Device_OS. All four columns are populated. 'Data' file has these same columns, with Device... More on stackoverflow.com
🌐 stackoverflow.com
python - What is the best way to implement nested dictionaries? - Stack Overflow
and now my_shnazzy_dictionary has all your values. If you needed to do this on the fly, you can create the YAML as a string and feed that into yaml.safe_load(...). ... YAML is my definitely my choice for inputting lots of deeply nested data (and configuration files, databaes mockups, etc...). If the OP doesn't want extra files lying around, just use a regular Python ... More on stackoverflow.com
🌐 stackoverflow.com
python - Best way to get nested dictionary items - Stack Overflow
The topic is not new and has already been discussed in multiple posts (links at the bottom). However, I felt like the resources are scattered and it is not always clear what the the best approach i... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Programiz
programiz.com › python-programming › nested-dictionary
Python Nested Dictionary (With Examples)
The second loop goes through the information of each person. Then, it returns all of the keys name, age, sex of each person's dictionary. Now, we print the key of the person’s information and the value for that key. Nested dictionary is an unordered collection of dictionary
🌐
Reddit
reddit.com › r/learnpython › multiple dictionaries versus nested dictionary?
r/learnpython on Reddit: Multiple dictionaries versus nested dictionary?
June 7, 2022 -

Hello,

What should I take into consideration when building multiple dictionaries to join them versus one nested dictionary with all the keys together? Will one cause more headaches than the other? In my project, the nested dictionary would have 9 keys.

For example:

    {'Name':{0: 'Ben',1: 'Jerry'}}

    {'Age':{0: 21,1: 22}}

    versus

    {{Name: 'Ben', Age:21,},
     {Name: 'Jerry', Age: 22}}

Update: Thanks everyone for your help and input, you've given me a lot to think, learn, and made me realize I need to continue learning use cases for tuples, dataclasses, dic, nested dic, and etc. Thanks again!

🌐
Career Karma
careerkarma.com › blog › python › python nested dictionary: a how-to guide
Python Nested Dictionary: A How-To Guide | Career Karma
December 1, 2023 - A nested dictionary is a dictionary inside of a dictionary. On Career Karma, learn how to create and use Python nested dictionaries.
🌐
Medium
bond-kirill-alexandrovich.medium.com › nested-dictionaries-in-python-5a362e03ec6c
Nested dictionaries in Python. In this article I will show you what is… | by Kirill Bondarenko | Medium
June 24, 2020 - Nested dictionaries in Python In this article I will show you what is a nested dictionary and how to work with it efficient (get ,set values). Introduction How often you need to use nested dictionary …
🌐
SitePoint
sitepoint.com › python hub › nested dictionaries
Python - Nested Dictionaries | SitePoint — SitePoint
Understand nested dictionaries in Python: creating, accessing, and modifying multilevel data structures. Guide for beginners.
Find elsewhere
🌐
Learn By Example
learnbyexample.org › python-nested-dictionary
Python Nested Dictionary - Learn By Example
June 20, 2024 - A nested dictionary is a dictionary where each key can map to another dictionary rather than a simple value like an integer or string. This can be extended to multiple levels, creating a hierarchy of dictionaries.
Top answer
1 of 10
427

A nested dict is a dictionary within a dictionary. A very simple thing.

Copy>>> d = {}
>>> d['dict1'] = {}
>>> d['dict1']['innerkey'] = 'value'
>>> d['dict1']['innerkey2'] = 'value2'
>>> d
{'dict1': {'innerkey': 'value', 'innerkey2': 'value2'}}

You can also use a defaultdict from the collections package to facilitate creating nested dictionaries.

Copy>>> import collections
>>> d = collections.defaultdict(dict)
>>> d['dict1']['innerkey'] = 'value'
>>> d  # currently a defaultdict type
defaultdict(<type 'dict'>, {'dict1': {'innerkey': 'value'}})
>>> dict(d)  # but is exactly like a normal dictionary.
{'dict1': {'innerkey': 'value'}}

You can populate that however you want.

I would recommend in your code something like the following:

Copyd = {}  # can use defaultdict(dict) instead

for row in file_map:
    # derive row key from something 
    # when using defaultdict, we can skip the next step creating a dictionary on row_key
    d[row_key] = {} 
    for idx, col in enumerate(row):
        d[row_key][idx] = col

According to your comment:

may be above code is confusing the question. My problem in nutshell: I have 2 files a.csv b.csv, a.csv has 4 columns i j k l, b.csv also has these columns. i is kind of key columns for these csvs'. j k l column is empty in a.csv but populated in b.csv. I want to map values of j k l columns using 'i` as key column from b.csv to a.csv file

My suggestion would be something like this (without using defaultdict):

Copya_file = "path/to/a.csv"
b_file = "path/to/b.csv"

# read from file a.csv
with open(a_file) as f:
    # skip headers
    f.next()
    # get first colum as keys
    keys = (line.split(',')[0] for line in f) 

# create empty dictionary:
d = {}

# read from file b.csv
with open(b_file) as f:
    # gather headers except first key header
    headers = f.next().split(',')[1:]
    # iterate lines
    for line in f:
        # gather the colums
        cols = line.strip().split(',')
        # check to make sure this key should be mapped.
        if cols[0] not in keys:
            continue
        # add key to dict
        d[cols[0]] = dict(
            # inner keys are the header names, values are columns
            (headers[idx], v) for idx, v in enumerate(cols[1:]))

Please note though, that for parsing csv files there is a csv module.

2 of 10
70

UPDATE: For an arbitrary length of a nested dictionary, go to this answer.

Use the defaultdict function from the collections.

High performance: "if key not in dict" is very expensive when the data set is large.

Low maintenance: make the code more readable and can be easily extended.

Copyfrom collections import defaultdict

target_dict = defaultdict(dict)
target_dict[key1][key2] = val
🌐
OpenStax
openstax.org › books › introduction-python-programming › pages › 10-5-nested-dictionaries-and-dictionary-comprehension
10.5 Nested dictionaries and dictionary comprehension - Introduction to Python Programming | OpenStax
March 13, 2024 - As described before, Python dictionaries are a type of data structure that allows for storing data in key-value pairs. Nested dictionaries are dictionaries that are stored as values within another dictionary.
🌐
Medium
medium.com › @ryan_forrester_ › python-nested-dictionaries-complete-guide-8a61b88a2e02
Python Nested Dictionaries: Complete Guide | by ryan | Medium
October 24, 2024 - Python Nested Dictionaries: Complete Guide Nested dictionaries are essential when you need to organize complex, hierarchical data in Python. They’re particularly useful for working with JSON data …
🌐
Tutorialspoint
tutorialspoint.com › python › python_nested_dictionaries.htm
Python - Nested Dictionaries
Nested dictionaries in Python refer to dictionaries that are stored as values within another dictionary. In other words, a dictionary can contain other dictionaries as its values, forming a hierarchical or nested structure.
🌐
datagy
datagy.io › home › python posts › python dictionaries › python nested dictionary: complete guide
Python Nested Dictionary: Complete Guide • datagy
December 15, 2022 - In this tutorial, you’ll learn about Python nested dictionaries – dictionaries that are the values of another dictionary. You’ll learn how to create nested dictionaries, access their elements, modify them and more. You’ll also learn how to work with nested dictionaries to convert them to a Pandas DataFrame.
🌐
Scaler
scaler.com › home › topics › what is nested dictionary in python?
What is Nested Dictionary in Python? | Scaler Topics
May 4, 2023 - We can define a dictionary by enclosing a comma-separated list of key-value pairs in curly braces ({}). A colon (:) separates each key from its associated value. In Python, a nested dictionary is a dictionary inside a dictionary.
Top answer
1 of 16
211

What is the best way to implement nested dictionaries in Python?

This is a bad idea, don't do it. Instead, use a regular dictionary and use dict.setdefault where apropos, so when keys are missing under normal usage you get the expected KeyError. If you insist on getting this behavior, here's how to shoot yourself in the foot:

Implement __missing__ on a dict subclass to set and return a new instance.

This approach has been available (and documented) since Python 2.5, and (particularly valuable to me) it pretty prints just like a normal dict, instead of the ugly printing of an autovivified defaultdict:

class Vividict(dict):
    def __missing__(self, key):
        value = self[key] = type(self)() # retain local pointer to value
        return value                     # faster to return than dict lookup

(Note self[key] is on the left-hand side of assignment, so there's no recursion here.)

and say you have some data:

data = {('new jersey', 'mercer county', 'plumbers'): 3,
        ('new jersey', 'mercer county', 'programmers'): 81,
        ('new jersey', 'middlesex county', 'programmers'): 81,
        ('new jersey', 'middlesex county', 'salesmen'): 62,
        ('new york', 'queens county', 'plumbers'): 9,
        ('new york', 'queens county', 'salesmen'): 36}

Here's our usage code:

vividict = Vividict()
for (state, county, occupation), number in data.items():
    vividict[state][county][occupation] = number

And now:

>>> import pprint
>>> pprint.pprint(vividict, width=40)
{'new jersey': {'mercer county': {'plumbers': 3,
                                  'programmers': 81},
                'middlesex county': {'programmers': 81,
                                     'salesmen': 62}},
 'new york': {'queens county': {'plumbers': 9,
                                'salesmen': 36}}}

Criticism

A criticism of this type of container is that if the user misspells a key, our code could fail silently:

>>> vividict['new york']['queens counyt']
{}

And additionally now we'd have a misspelled county in our data:

>>> pprint.pprint(vividict, width=40)
{'new jersey': {'mercer county': {'plumbers': 3,
                                  'programmers': 81},
                'middlesex county': {'programmers': 81,
                                     'salesmen': 62}},
 'new york': {'queens county': {'plumbers': 9,
                                'salesmen': 36},
              'queens counyt': {}}}

Explanation:

We're just providing another nested instance of our class Vividict whenever a key is accessed but missing. (Returning the value assignment is useful because it avoids us additionally calling the getter on the dict, and unfortunately, we can't return it as it is being set.)

Note, these are the same semantics as the most upvoted answer but in half the lines of code - nosklo's implementation:

class AutoVivification(dict):
    """Implementation of perl's autovivification feature."""
    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            value = self[item] = type(self)()
            return value

Demonstration of Usage

Below is just an example of how this dict could be easily used to create a nested dict structure on the fly. This can quickly create a hierarchical tree structure as deeply as you might want to go.

import pprint

class Vividict(dict):
    def __missing__(self, key):
        value = self[key] = type(self)()
        return value

d = Vividict()

d['foo']['bar']
d['foo']['baz']
d['fizz']['buzz']
d['primary']['secondary']['tertiary']['quaternary']
pprint.pprint(d)

Which outputs:

{'fizz': {'buzz': {}},
 'foo': {'bar': {}, 'baz': {}},
 'primary': {'secondary': {'tertiary': {'quaternary': {}}}}}

And as the last line shows, it pretty prints beautifully and in order for manual inspection. But if you want to visually inspect your data, implementing __missing__ to set a new instance of its class to the key and return it is a far better solution.

Other alternatives, for contrast:

dict.setdefault

Although the asker thinks this isn't clean, I find it preferable to the Vividict myself.

d = {} # or dict()
for (state, county, occupation), number in data.items():
    d.setdefault(state, {}).setdefault(county, {})[occupation] = number

and now:

>>> pprint.pprint(d, width=40)
{'new jersey': {'mercer county': {'plumbers': 3,
                                  'programmers': 81},
                'middlesex county': {'programmers': 81,
                                     'salesmen': 62}},
 'new york': {'queens county': {'plumbers': 9,
                                'salesmen': 36}}}

A misspelling would fail noisily, and not clutter our data with bad information:

>>> d['new york']['queens counyt']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'queens counyt'

Additionally, I think setdefault works great when used in loops and you don't know what you're going to get for keys, but repetitive usage becomes quite burdensome, and I don't think anyone would want to keep up the following:

d = dict()

d.setdefault('foo', {}).setdefault('bar', {})
d.setdefault('foo', {}).setdefault('baz', {})
d.setdefault('fizz', {}).setdefault('buzz', {})
d.setdefault('primary', {}).setdefault('secondary', {}).setdefault('tertiary', {}).setdefault('quaternary', {})

Another criticism is that setdefault requires a new instance whether it is used or not. However, Python (or at least CPython) is rather smart about handling unused and unreferenced new instances, for example, it reuses the location in memory:

>>> id({}), id({}), id({})
(523575344, 523575344, 523575344)

An auto-vivified defaultdict

This is a neat looking implementation, and usage in a script that you're not inspecting the data on would be as useful as implementing __missing__:

from collections import defaultdict

def vivdict():
    return defaultdict(vivdict)

But if you need to inspect your data, the results of an auto-vivified defaultdict populated with data in the same way looks like this:

>>> d = vivdict(); d['foo']['bar']; d['foo']['baz']; d['fizz']['buzz']; d['primary']['secondary']['tertiary']['quaternary']; import pprint; 
>>> pprint.pprint(d)
defaultdict(<function vivdict at 0x17B01870>, {'foo': defaultdict(<function vivdict 
at 0x17B01870>, {'baz': defaultdict(<function vivdict at 0x17B01870>, {}), 'bar': 
defaultdict(<function vivdict at 0x17B01870>, {})}), 'primary': defaultdict(<function 
vivdict at 0x17B01870>, {'secondary': defaultdict(<function vivdict at 0x17B01870>, 
{'tertiary': defaultdict(<function vivdict at 0x17B01870>, {'quaternary': defaultdict(
<function vivdict at 0x17B01870>, {})})})}), 'fizz': defaultdict(<function vivdict at 
0x17B01870>, {'buzz': defaultdict(<function vivdict at 0x17B01870>, {})})})

This output is quite inelegant, and the results are quite unreadable. The solution typically given is to recursively convert back to a dict for manual inspection. This non-trivial solution is left as an exercise for the reader.

Performance

Finally, let's look at performance. I'm subtracting the costs of instantiation.

>>> import timeit
>>> min(timeit.repeat(lambda: {}.setdefault('foo', {}))) - min(timeit.repeat(lambda: {}))
0.13612580299377441
>>> min(timeit.repeat(lambda: vivdict()['foo'])) - min(timeit.repeat(lambda: vivdict()))
0.2936999797821045
>>> min(timeit.repeat(lambda: Vividict()['foo'])) - min(timeit.repeat(lambda: Vividict()))
0.5354437828063965
>>> min(timeit.repeat(lambda: AutoVivification()['foo'])) - min(timeit.repeat(lambda: AutoVivification()))
2.138362169265747

Based on performance, dict.setdefault works the best. I'd highly recommend it for production code, in cases where you care about execution speed.

If you need this for interactive use (in an IPython notebook, perhaps) then performance doesn't really matter - in which case, I'd go with Vividict for readability of the output. Compared to the AutoVivification object (which uses __getitem__ instead of __missing__, which was made for this purpose) it is far superior.

Conclusion

Implementing __missing__ on a subclassed dict to set and return a new instance is slightly more difficult than alternatives but has the benefits of

  • easy instantiation
  • easy data population
  • easy data viewing

and because it is less complicated and more performant than modifying __getitem__, it should be preferred to that method.

Nevertheless, it has drawbacks:

  • Bad lookups will fail silently.
  • The bad lookup will remain in the dictionary.

Thus I personally prefer setdefault to the other solutions, and have in every situation where I have needed this sort of behavior.

2 of 16
193
class AutoVivification(dict):
    """Implementation of perl's autovivification feature."""
    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            value = self[item] = type(self)()
            return value

Testing:

a = AutoVivification()

a[1][2][3] = 4
a[1][3][3] = 5
a[1][2]['test'] = 6

print a

Output:

{1: {2: {'test': 6, 3: 4}, 3: {3: 5}}}
🌐
Spark By {Examples}
sparkbyexamples.com › home › python › how to create nested dictionary in python
How to Create Nested Dictionary in Python - Spark By {Examples}
May 31, 2024 - Nested dictionary in Python is a dictionary within another dictionary. This means that the values of the outer dictionary are themselves dictionaries. This allows you to create a hierarchical structure, providing a way to organize and manage ...
Top answer
1 of 3
6

I will propose 5 different solutions to get items in a nested dictionary that meet the criteria. Then, I will compare them based on the performance and readability. Conclusions at the end.

Possible solutions

  1. Use a for loop:
def getitem_for(d, key):
    for level in key:
        d = d[level]
    return d
  1. Use while
def getitem_while(d, key):
    while key:
        d = d[key[0]]
        key = key[1:]
    return d
  1. Use reduce
from functools import reduce
from operator import getitem

def getitem_reduce(d, key):
    return reduce(getitem, key, d)
  1. Use recursion
def getitem_recursive(d, key):
    if len(key) !=  1:
        return getitem_recursive(d[key[0]], key[1:])
    else:
        return d[key[0]]
  1. Finally, we can flatten the dictionary so that its keys are tuples, where each element represents a certain level. To flatten the dictionary:
def flatten(ndict):
    def key_value_pairs(d, key=[]):
        if not isinstance(d, dict):
            yield tuple(key), d
        else:
            for level, d_sub in d.items():
                key.append(level)
                yield from key_value_pairs(d_sub, key)
                key.pop()
    return dict(key_value_pairs(ndict))
>>> fd = flatten(d)
>>> fd
{('a', 'b', 'c'): 0, ('b', 'c'): 1, ('c',): 2}

Getting items is now trivial

>>> fd["a", "b", "c"]
0

Discussion

In terms of readability I find 1, 2, and 3 almost equivalent. Maybe reduce is not as well known as for and while loops, but still results in an elegant and concise one-liner. The recursive solutions 4 and 5 may be more difficult to understand, especially for beginners.

Now performance, here you have the simple speed tests that I ran in a Jupyter notebook on Python 3.8.

%%timeit
getitem_for(d, key)
346 ns ± 17.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%%timeit
getitem_while(d, key)
817 ns ± 67.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%%timeit
getitem_reduce(d, key)
445 ns ± 11.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%%timeit
getitem_recursive(d, key)
1.06 µs ± 69.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%%timeit
df[key]
112 ns ± 3.95 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

The best approach seems to be the flattened dictionary; however, here it is how long it takes to create it from the original one:

%%timeit
flatten(d)
7.96 µs ± 779 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

The recursive function and while loop are definitely to exclude. The for loop and reduce versions are comparable, even though the for loop is faster.

Conclusions

The performance tests that I run are not precise, do not necessarily apply to all nested dictionaries and Python versions. However, they help identify the for loop and reduce versions as good candidates to efficiently get the items of a nested dictionary. All solutions investigated fail noisily when trying to get a key does not exist.

Flat dictionaries are by far superior to all other options, but one must take into account the cost of flattening. This shows that you should prefer flat dictionaries over nested whenever you have control over the source of data.

2 of 3
3

You could use python-benedict (I developed it), it's dict wrapper with many reusable features, including keypath support.

The library code is open-source and available on GitHub: https://github.com/fabiocaccamo/python-benedict

Installation:

pip install python-benedict

Usage:

from benedict import benedict

d = {"a": {"b": {"c" : 0}},
     "b": {"c" : 1},
     "c": 2}

key = ["a", "b", "c"]

b = benedict(d)
print(b[key)) # -> 0
🌐
iO Flood
ioflood.com › blog › python-nested-dictionary
Python Nested Dictionary Guide (With Examples)
January 30, 2024 - Use a default dictionary: Python’s collections module has a defaultdict class that you can use to provide a default value for keys that don’t exist in the dictionary. Working with nested dictionaries can be tricky, but with these tips and a bit of practice, you’ll be able to handle them effectively.