tags:

views:

94

answers:

3
+3  Q: 

python dictionary

>>> d2
{'egg': 3, 'ham': {'grill': 4, 'fry': 6, 'bake': 5}, 'spam': 2}
>>> d2.get('spamx',99)
99
>>> d2.get('ham')['fry']
6

I want to get value of fry inside of ham, if not, get value, 99 or 88 as the 2nd example. But how?

+8  A: 
d2.get('ham', {}).get('fry', 88)

I would probably break it down into several statements in real life.

ham = d2.get('ham', {})
fry = ham.get('fry', 88)
Oddthinking
rather `d2.get('ham', {}).get('fry', 99)`, not ? (DRY!)
mykhal
+1 for being right
aaronasterling
or 88 ? (btw: tag should be homework:-)
ralf.w.
@mykhal, good call. Fixed.
Oddthinking
Making something readable != repeating yourself. Repeating yourself would be to write a function to get ham's fry, and then another function to get spam's fry, when both functions could be written as one function which takes ham/spam as a parameter.
Jesse Dhillon
@Jesse, The previous version had two references to 'fry' and two references to the magic number being returned. The suggestion was a distinct improvement.
Oddthinking
I'm not seeing that version anywhere.
Jesse Dhillon
@Jesse, odd. Neither am I. It took me about 3 or 4 edits to get this right, but SO seems to have collapsed it into 1, making me look far more decisive than I am.
Oddthinking
@Oddthinking, I think if the edits are clustered within a certain window of time, they are collapsed.
Jesse Dhillon
+2  A: 

For the default values of get to work correctly the first default needs to be a dictionary, so that you can chain the .get calls correctly if the first fails.

d.get('ham',{}).get('fry',88)

you could also use a try, except block

def get_ham_fry()
  try:
    return d['ham']['fry']
  except AttributeError,e:
    return 88
Michael Anderson
+1  A: 

If you need to do this a lot, you can write a helper function

def get_nested(d, list_of_keys, default):
    for k in list_of_keys:
        if k not in d: 
            return default
        d=d[k]
    return d

print get_nested(d2,['ham','spam'],99)
print get_nested(d2,['ham','grill'],99)
gnibbler
Feels like reduce. `functools.reduce(lambda d,x: d[x] if x in d else default, ['ham','spam'], d2)`
KennyTM
@KennyTM, That raises a `TypeError` for `['bacon','spam']`
gnibbler
@gnibbler: ah right.
KennyTM