Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

recursive dictionary creation python

is there any way to dynamically create missing keys if i want to want to set a variable in a subdictionary.

essentially I want to create any missing keys and set my value.

self.portdict[switchname][str(neighbor['name'])]['local']['ports'] = []

currently i'm doing it but its messy:

if not switchname in self.portdict:
    self.portdict[switchname] = {}
if not str(neighbor['name']) in self.portdict[switchname]:
    self.portdict[switchname][str(neighbor['name'])] = {}
if not 'local' in self.portdict[switchname][str(neighbor['name'])]:
    self.portdict[switchname][str(neighbor['name'])]['local'] = {}
if not 'ports' in self.portdict[switchname][str(neighbor['name'])]['local']:
    self.portdict[switchname][str(neighbor['name'])]['local']['ports'] = []

Is there any way to do this in one or two lines instead?

like image 634
user1601716 Avatar asked May 09 '26 05:05

user1601716


2 Answers

This is easier to do without recursion:

def set_by_path(dct, path, value):
    ipath = iter(path)
    p_last = next(ipath)
    try:
        while True:
            p_next = next(ipath)
            dct = dct.setdefault(p_last, {})
            p_last = p_next
    except StopIteration:
        dct[p_last] = value

And a test case:

d = {}
set_by_path(d, ['foo', 'bar', 'baz'], 'qux')
print d  # {'foo': {'bar': {'baz': 'qux'}}}

If you want to have it so you don't need a function, you can use the following defaultdict factory which allows you to nest things arbitrarily deeply:

from collections import defaultdict

defaultdict_factory = lambda : defaultdict(defaultdict_factory)

d = defaultdict_factory()
d['foo']['bar']['baz'] = 'qux'
print d
like image 132
mgilson Avatar answered May 11 '26 19:05

mgilson


Use collections.defaultdict

self.portdict = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: []))))
like image 30
o11c Avatar answered May 11 '26 19:05

o11c