Currently I am using the following method, assume dictionary
data[a][b][c]
I use:
if "a" in data and "b" in data["a"] and "c" in data["a"]["b"]:
...
Are there any better way?
You can wrap it in a try/except block
try:
x = data[a][b][c]
...do stuff in your "if" clause
except KeyError:
...do stuff in your "else" clause
I would typically use the pattern
foo = data.get("a",{}).get("b",{}).get("c",False)
if foo:
...
This requires that the nesting is always the same depth and that data["a"]["b"]["c"] is not "falsy".
If you need to do this multi-level lookup very often, this helper method can be useful:
def multi_get(dict_obj, *attrs, default=None):
result = dict_obj
for attr in attrs:
if attr not in result:
return default
result = result[attr]
return result
To use it, just call it like:
x = multi_get(data, 'a', 'b', 'c', default=False)
There's two solutions:
You can use a defaultdict
, and intstantiate an inner level with another defaultdict
. Then, if the key is missing, it'll return an empty dict without throwing errors:
from collections import defaultdict
>>> d = defaultdict(lambda: defaultdict(dict))
>>> d['a']['b']
{}
If you need more levels, you just have to chain many lambda
.
Partial reference: Multiple levels of 'collection.defaultdict' in Python
Another way is to surronding the dict access with try
/except
block and manage the missing key through the KeyError
exception (stop the program, return a default value, etc.)
try:
x = data[a][b][c]
# same code of your if statement
except KeyError:
# stuff you do in your else