Pythonic way to make sure a list exists in the key of the key before adding
I am asking this in terms of what my impression is that it is more Pythonic to ask for forgiveness than permission.
So, I have some code that I like:
d = dict()
try:
d[est['state']].append(est)
except Exception:
d[est['state']] = []
d[est['state']].append(est)
In the above code, I am sorry and not permission by repeating myself, which is pretty lame! Therefore, knowing the alternatives, I would prefer:
d = dict()
if est['state'] in d:
d[est['state']].append(est)
else:
d[est['state']] = [est]
Both of these approaches seem crude. What's the best way to do this? The best I've found so far:
from collections import defaultdict
d = defaultdict(list)
d[est['state']].append(est)
source to share
The pythonic way is the last one you already discovered: defaultdict is a subclass of a subclass that calls a factory function to pass in missing values. It is available in python version 2.5 and above.
>>> import collections
>>> d = collections.defaultdict(list)
>>> d[0].append('potato')
>>> d
defaultdict(<type 'list'>, {0: ['potato']})
It exists for this very purpose, so avoid dict.setdefault
hacks if possible.
source to share
You can try comparing several different approaches if speed is a concern. I tried the "if key in dictionary" approach and found try / except, on average, 10% faster. I find that my best Python practices for such matters change every few years. This answer might be helpful if you need Python 2.4 compatibility.
Using your example, I would:
d = {}
# Confirm separately that est['state'] does not raise a KeyError.
state = est['state']
try:
l = d[state]
except KeyError:
l = []
d[state] = l
l.append(est)
source to share