6

Imagine you have a dictionary in python: myDic = {'a':1, 'b':{'c':2, 'd':3}}. You can certainly set a variable to a key value and use it later, such as:

myKey = 'b'
myDic[myKey]
>>> {'c':2, 'd':3}

However, is there a way to somehow set a variable to a value that, when used as a key, will dig into sub dictionaries as well? Is there a way to accomplish the following pseudo-code in python?

myKey = "['b']['c']"
myDic[myKey]
>>> 2

So first it uses 'b' as a key, and whatever is reurned it then uses 'c' as a key on that. Obviously, it would return an error if the value returned from the first lookup is not a dictionary.

J-bob
  • 8,380
  • 11
  • 52
  • 85
  • See the answer to [this question](http://stackoverflow.com/questions/3122566/in-a-python-dict-of-dicts-how-do-you-emulate-perls-auto-vivification-behavior/3122575#3122575) – Burhan Khalid Dec 13 '12 at 04:36

5 Answers5

6

No, there is nothing you can put into a variable so that myDict[myKey] will dig into the nested dictionaries.

Here is a function that may work for you as an alternative:

def recursive_get(d, keys):
    if len(keys) == 1:
        return d[keys[0]]
    return recursive_get(d[keys[0]], keys[1:])

Example:

>>> myDic = {'a':1, 'b':{'c':2, 'd':3}}
>>> recursive_get(myDic, ['b', 'c'])
2
Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • Ok, I had originally considered just implementing the recursive method you've shown here, but was holding out out see if there was something built-in to do the job because I also wanted this nested capability for setting values and checking if `nested_key in dic`. But Since there doesn't seem to be an alternative, I'll take this answer and just implement any other functionality manually. – J-bob Dec 13 '12 at 05:11
3

No, not with a regular dict. With myDict[key] you can only access values that are actually values of myDict. But if myDict contains other dicts, the values of those nested dicts are not values of myDict.

Depending on what you're doing with the data structure, it may be possible to get what you want by using tuple keys instead of nested dicts. Instead of having myDic = {'b':{'c':2, 'd':3}}, you could have myDic = {('b', 'c'):2, ('b', 'd'): 3}. Then you can access the values with something like myDic['b', 'c']. And you can indeed do:

val = 'b', 'c'
myDic[val]
BrenBarn
  • 242,874
  • 37
  • 412
  • 384
2

AFAIK, you cannot. If you think about the way python works, it evaluates inside out, left to right. [] is a shorthand for __getitem__ in this case. Thus you would need to parse the arguments you are passing into __getitem__ (whatever you pass in) and handle that intelligently. If you wanted to have such behavior, you would need to subclass/write your own dict class.

Snakes and Coffee
  • 8,747
  • 4
  • 40
  • 60
0
myDict = {'a':1, 'b':{'c':2, 'd':3}}
k = 'b'

myDict.get(k) should give
{'c':2, 'd':3}

and either
d.get(k)['c'] 
OR

k1 = 'c'
d.get(k).key(k1) should give 2
srhegde
  • 573
  • 4
  • 3
0

Pretty old question. There is no builtin function for that.

Compact solution using functools.reduce and operator.getitem:

from functools import reduce
from operator import getitem

d = {'a': {'b': ['banana', 'lemon']}}
p = ['a', 'b', 1]

v = reduce(getitem, p, d)
# 'lemon'
David Rissato Cruz
  • 3,347
  • 2
  • 17
  • 17