If I have a dict, d and I want to check a value at d['e']['foo']['bar']
where e and foo are dictionaries and bar gives a string what is a way to SAFELY get the value at that location? Is there anything beyond a try catch?
Asked
Active
Viewed 96 times
0

Bren
- 3,516
- 11
- 41
- 73
-
You could try using `collections.defaultdict()`s. See http://stackoverflow.com/questions/5029934/python-defaultdict-of-defaultdict – synchronizer Feb 27 '17 at 03:49
-
@synchronizer and then just check that the value is a "real" one or not. Thanks! – Bren Feb 27 '17 at 03:52
-
Just to be sure, I'm writing a quick program to validate what I said. – synchronizer Feb 27 '17 at 03:58
-
*no, I can't seem to get more than one nested defaultdict – synchronizer Feb 27 '17 at 04:03
-
@synchronizer yes, it *can* get more than one nested structure, but that doesn't matter, because `defaultdict` doesn't really answer the question. A `defaultdict` doesn't check that, it creates a value *by default* – juanpa.arrivillaga Feb 27 '17 at 04:17
-
So, what exactly do you mean by "safely"? What isn't safe about a try-catch? – juanpa.arrivillaga Feb 27 '17 at 04:18
-
@juanpa.arrivillaga I think that Bren wanted a way to abstract away the process of checking whether an item already existed in the dictionary. A defaultdict works for that, though yes, it creates default values. Out of curiosity, how do you nest more than one defaultdict? I was only able to do this with one nesting before there was an error (using a lambda). – synchronizer Feb 27 '17 at 04:23
-
1@synchronizer from [the man himself](https://twitter.com/raymondh/status/343823801278140417). – juanpa.arrivillaga Feb 27 '17 at 04:24
-
@juanpa.arrivillaga well I asked for beyond a try-catch, which I am sure is safe. That seems to be the best way. I thought maybe some abstraction might exist like synchronizer mentioned. I try to use try-catch as a last resort maybe I should abandon that practice. – Bren Feb 27 '17 at 04:49
-
Possible duplicate of [Python safe method to get value of nested dictionary](http://stackoverflow.com/questions/25833613/python-safe-method-to-get-value-of-nested-dictionary) – miradulo Feb 27 '17 at 14:32
4 Answers
3
A good way would be to use reduce
.
d={'e':{'foo':{'bar':"final value"}}}
l=['e','foo','bar']
print reduce(lambda x,y:x.get(y),l, d)
You can make a function
and pass a list
to it.
Output:final value

vks
- 67,027
- 10
- 91
- 124
-
@but if it a key-val pair is missing you get an exception. I think adding .get(y, default) would work to eliminate that. Though then I'd get a Type exception for None.get – Bren Feb 27 '17 at 05:58
-
@Bren but in any case you will have to handle such a case.....but in this method you can use variable values in list...its a generic function....i leave error handling to you....`.get` has a default value of `None`.You can have `exception` der – vks Feb 27 '17 at 06:01
-
-
@Bren For a version that does not require `try-except` from the user, modify like this: `x.get(y) if x else None`. – FMc Feb 27 '17 at 17:00
-
-
@vks Of course. But that adjustment eliminates the need for `try-except` if any keys (as opposed to just the last one) are missing. – FMc Feb 27 '17 at 17:57
1
Use get
with a default of an empty dictionary:
>>> d = {'e':{'foo':{'bar':0}}}
>>> print(d.get('e', {}).get('foo', {}).get('bar'))
0
>>> print(d.get('f', {}).get('doo', {}).get('car'))
None
>>> print(d.get('e', {}).get('foo', {}).get('car'))
None
>>> print(d.get('e', {}).get('doo', {}).get('bar'))
None

TigerhawkT3
- 48,464
- 6
- 60
- 97
1
One approach is to use a simple helper function along these lines:
def dive(d, *ks):
for k in ks:
if isinstance(d, dict) and k in d:
d = d[k]
else:
return None
return d
examples = [
{},
{'e': {'foo': 12}},
{'e': {'foo': {'bar': 999}}},
]
for i, e in enumerate(examples):
print(i, dive(e, 'e', 'foo', 'bar'))
Output:
(0, None)
(1, None)
(2, 999)

FMc
- 41,963
- 13
- 79
- 132
0
Make sure keys are in this dict,you can just try this:
if "e" in d:
print d["e"]
Or try to use get method,if key is not available then returns default value.
Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.
d.get("e","default value")

McGrady
- 10,869
- 13
- 47
- 69