I'm interrogating a nested dictionary using the dict.get('keyword') method. Currently my syntax is...
M = cursor_object_results_of_db_query
for m in M:
X = m.get("gparents").get("parent").get("child")
for x in X:
y = x.get("key")
However, sometimes one of the "parent" or "child" tags doesn't exist, and my script fails. I know using get()
I can include a default in the case the key doesn't exist of the form...
get("parent", '') or
get("parent", 'orphan')
But if I include any Null
, ''
, or empty I can think of, the chained .get("child")
fails when called on ''.get("child")
since ""
has no method .get()
.
The way I'm solving this now is by using a bunch of sequential try-except
around each .get("")
call, but that seems foolish and unpython---is there a way to default return "skip"
or "pass"
or something that would still support chaining and fail intelligently, rather than deep-dive into keys that don't exist?
Ideally, I'd like this to be a list comprehension of the form:
[m.get("gparents").get("parent").get("child") for m in M]
but this is currently impossible when an absent parent causes the .get("child")
call to terminate my program.
Since these are all python
dict
s and you are calling thedict.get()
method on them, you can use an emptydict
to chain:By leaving off the default for the last
.get()
you fall back toNone
. Now, if any of the intermediary keys is not found, the rest of the chain will use empty dictionaries to look things up, terminating in.get('child')
returningNone
.How about using a small helper function?
and then
Another approach is to recognize that if the key isn't found,
dict.get
returnsNone
. However,None
doesn't have an attribute.get
, so it will throw anAttributeError
:Just like Martijn's answer, this doesn't guarantee that
X
is iterable (non-None
). Although, you could fix that by making the lastget
in the chain default to returning an empty list:Finally, I think that probably the best solution to this problem is to use
reduce
:The advantage here is that you know if any of the
get
s failed based on the type of exception that was raised. It's possible that aget
returns the wrong type, then you get aTypeError
. If the dictionary doesn't have the key however, it raises aKeyError
. You can handle those separately or together. Whatever works best for your use case.I realise I'm a bit late for the part but here's the solution I came up with when faced with a similar problem:
For example: