2013-11-13 2 views
2

Есть ли стандартный способ получения значений из вложенных словарей? Функция относительно проста в написании, но мне любопытно, есть ли что-то уже в PSL или языке, который можно было бы использовать таким образом?Захват значений из вложенных словарей

Вот пример того, что я имею в виду:

def grab_from_dict(d, *keys): 
    assert isinstance(d, dict), 'd must be of type dict' 

    current_dict = d 
    for key in keys[0 : -1]: 
     if key not in current_dict: 
      return None 

     current_dict = current_dict[key] 

    if current_dict is None: 
     return None 

    return current_dict.get(keys[-1], None) 

d = { 
    'a' : { 
     'b' : { 
      'c1' : { 
       'd' : 'leeloo' 
      }, 
      'c2' : { 
       'd' : None 
      }, 
      'c3' : { 
       'e' : None 
      }, 
      'c4' : None 
     } 
    } 
} 

print grab_from_dict(d, 'a', 'b', 'c1') 
> {'d': 'leeloo'} 
print grab_from_dict(d, 'a', 'b', 'c1', 'd') 
> leeloo 
print grab_from_dict(d, 'a', 'b', 'c2') 
> {'d': None} 
print grab_from_dict(d, 'a', 'b', 'c2', 'd') 
> None 
print grab_from_dict(d, 'a', 'b', 'c3') 
> {'e': None} 
print grab_from_dict(d, 'a', 'b', 'c3', 'd') 
> None 
print grab_from_dict(d, 'a', 'b', 'c4') 
> None 
print grab_from_dict(d, 'a', 'b', 'c4', 'd') 
> None 
print grab_from_dict(d, 'a', 'b', 'c5') 
> None 
print grab_from_dict(d, 'a', 'b', 'c5', 'd') 
> None 

Это дает мне способ получить значение глубоко в вложенных словарях, не заботясь о существовании родительских словарей. Таким образом, вместо того, чтобы писать это:

value = None 
if 'a' in d and d['a'] not None: 
    if 'b' in d['a'] and d['a']['b'] is not None: 
     if 'c1' in d['a']['b'] and d['a']['b']['c1'] is not None: 
      value = d['a']['b']['c1'].get('d', None) 
print value 
> leeloo 

Я могу написать это:

value = grab_from_dict(d, 'a', 'b', 'c1', 'd') 
print value 
> leeloo 

Если какой-либо из родителей отсутствует, то функция просто возвращает None:

value = grab_from_dict(d, 'a', 'a', 'c1', 'd') 
print value 
> None 
+5

Ну, это будет просто 'd ['a'] ['b'] ['c1']'. На самом деле нет необходимости в какой-либо функции ... – jazzpi

+2

'reduce (dict.get, keys, the_dict)'. (в python3 вам нужно 'from functools import reduce'). Для отсутствующих ключей вы можете предложить лучший первый аргумент, который не вызывает ошибку (не проверен: 'lambda d, key: d.get (key), если d не является None else None') – Bakuriu

+0

Нет необходимости в функции , если вы не хотите проверки ошибок. :) – dstromberg

ответ

0

Почему вы ищете функционировать? Разве это не охватывает то, что вы ищете?

>>> d['a']['b']['c1'] 
{'d': 'leeloo'} 
>>> d['a']['b']['c1']['d'] 
'leeloo' 
+0

Я добавил дополнительный пример, который разъясняет мотивацию моего вопроса. – LavaScornedOven

1

Ловля исключение должно работать:

try: 
    result = d['a']['b']['c1'] 
except KeyError: 
    result = None 
+0

Хотя я согласен, что это сработает, я хотел бы выразить без исключений ситуацию, которая довольно распространена в коде. – LavaScornedOven

1

Вы могли бы написать/найти пользовательский класс контейнера написанный с такого рода поведение (может быть, это имеет объект NoneDict, который возвращает себя, если вы пытаетесь получить ? ключ), но, возможно, более элегантное решение попробовать/за исключением блока:

try: 
    x = d['a']['b']['c5']['d'] 
except KeyError: 
    x = None 

, поскольку это действительно просто говорит программе, как обрабатывать ожидаемую ошибку. Я бы назвал этот маленький код блоком «pythonic» способом сделать это.

Смежные вопросы