Python использует строки в качестве ключей dict

avatar
MKUltra
1 июля 2021 в 16:17
111
3
3

У меня есть объект с похожей структурой на этот

myObj = {
    "subObj1":{"keyA":"valueA1"},
    "subObj2":{"keyA":"valueA2","keyB":"valueB2"},
    "subObj3":{"keyA":"valueA3","keyB":"valueB3", "keyC":{"keyA":"valueA3c"}},
}

Обычно я могу получить доступ к содержимому этого объекта аналогично этому

print(myObj['subObj1']['keyA'])
print(myObj['subObj2']['keyB'])
print(myObj['subObj3']['keyC']['keyA'])

Что вернет значения

alueA1
valueB2
valueA3c

Мне нужен способ доступа к содержимому моего объекта на основе ключей из внешнего файла конфигурации. Ключ из этого файла будет выглядеть следующим образом:

"subObj3.keyC.keyA"

Я могу преобразовать этот ключ во что-то похожее на то, как я обычно обращаюсь к объекту

keyString="['subObj3']['keyC']['keyA']"

Но при попытке доступа к объекту с помощью этой строки ключей я получаю сообщения KeyError

print(myObj[keyString])
KeyError: "['subObj3']['keyC']['keyA']"

Есть ли правильный синтаксис или лучший способ для того, что я пытаюсь здесь сделать?

Источник

Ответы (3)

avatar
BuddyBob
1 июля 2021 в 16:28
-1

Вы сказали, что можете преобразовать свою строку в

keyString="['subObj3']['keyC']['keyA']"

Это хорошо, потому что теперь вы можете преформировать eval() на этом.

string = ""
for i in "subObj3.keyC.keyA".split('.'):
    string += f"['{i}']"
print(eval(f'myObj{string}'))

выход

valueA3c
avatar
Stryder
1 июля 2021 в 16:27
1

Решение Nk03 действительно мощный метод... В качестве более простой альтернативы рассмотрим следующее:

def get_value(s):
    keys = s.split(".")
    d = myObj
    for k in keys: d = d[k] # will go a step deeper for each provided key
    return d

get_value("subObj3.keyC.keyA")
>> 'valueA3c'

get_value("subObj1.keyA")
>> 'valueA1'

get_value("subObj2.keyB")
>> 'valueB2'


avatar
Nk03
1 июля 2021 в 16:22
2

Вот один из способов через панд:

import pandas as pd
myObj = {
    "subObj1": {"keyA": "valueA1"},
    "subObj2": {"keyA": "valueA2", "keyB": "valueB2"},
    "subObj3": {"keyA": "valueA3", "keyB": "valueB3", "keyC": {"keyA": "valueA3c"}},
}
normalized_myObj = pd.json_normalize(myObj, sep='.').to_dict('records')

ВЫВОД:

[{'subObj1.keyA': 'valueA1',
  'subObj2.keyA': 'valueA2',
  'subObj2.keyB': 'valueB2',
  'subObj3.keyA': 'valueA3',
  'subObj3.keyB': 'valueB3',
  'subObj3.keyC.keyA': 'valueA3c'}]

ПРИМЕЧАНИЕ: использование pandas может быть излишним для этой задачи, но я предпочитаю однострочное решение.