I have written the following code in two different ways. I am trying to find the "correct pythonic" way of doing it. I will explain the reasons for both.
First way, EAFP. This one uses pythons EAFP priciple, but causes some code duplication.
try:
my_dict['foo']['bar'] = some_var
except KeyError:
my_dict['foo'] = {}
my_dict['foo']['bar'] = some_var
Second way, LBYL. LBYL is not exactly considered pythonic, but it removes the code duplication.
if 'foo' not in my_dict:
my_dict['foo'] = {}
my_dict['foo']['bar'] = some_var
Which way would be considered best? Or is there a better way?
I would say a seasoned Python developer would either use
dict.setdefault or collections.defaultdict
my_dict.setdefault('foo', {})['bar'] = some_var
or
from collection import defaultdict
my_dict = defaultdict(dict)
my_dict['foo']['bar'] = some_var
Also for the sake of completeness, I will introduce you to a recursive defaultdict
pattern, which allows for dictionaries with infinite depth without any key error
>>> from collections import defaultdict
>>> def tree(): return defaultdict(tree)
>>> my_dict = tree()
>>> my_dict['foo']['bar']['spam']['egg'] = 0
>>> my_dict
defaultdict(<function tree at 0x026FFDB0>, {'foo': defaultdict(<function tree at 0x026FFDB0>, {'bar': defaultdict(<function tree at 0x026FFDB0>, {'spam': defaultdict(<function tree at 0x026FFDB0>, {'egg': 0})})})})