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.
Access Values using get() Another way to access value(s) in a nested dictionary ( employees ) is to use the dict. get() method. This method returns the value for a specified key. If the specified key does not exist, the get() method returns None (preventing a KeyError ).
just write d. items() , it will work, by default on iterating the name of dict returns only the keys.
get()—method comes in: it returns the value for a specified key in a dictionary. This method will only return a value if the specified key is present in the dictionary, otherwise it will return None.
Addition of elements to a nested Dictionary can be done in multiple ways. One way to add a dictionary in the Nested dictionary is to add values one be one, Nested_dict[dict][key] = 'value'. Another way is to add the whole dictionary in one go, Nested_dict[dict] = { 'key': 'value'}.
Since these are all python dicts and you are calling the dict.get() method on them, you can use an empty dict to chain:
[m.get("gparents", {}).get("parent", {}).get("child") for m in M] By leaving off the default for the last .get() you fall back to None. 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') returning None.
Another approach is to recognize that if the key isn't found, dict.get returns None. However, None doesn't have an attribute .get, so it will throw an AttributeError:
for m in M: try: X = m.get("gparents").get("parent").get("child") except AttributeError: continue for x in X: y = x.get("key") #do something with `y` probably??? Just like Martijn's answer, this doesn't guarantee that X is iterable (non-None). Although, you could fix that by making the last get in the chain default to returning an empty list:
try: X = m.get("gparents").get("parent").get("child",[]) except AttributeError: continue Finally, I think that probably the best solution to this problem is to use reduce:
try: X = reduce(dict.__getitem__,["gparents","parent","child"],m) except (KeyError,TypeError): pass else: for x in X: #do something with x The advantage here is that you know if any of the gets failed based on the type of exception that was raised. It's possible that a get returns the wrong type, then you get a TypeError. If the dictionary doesn't have the key however, it raises a KeyError. You can handle those separately or together. Whatever works best for your use case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With