Страницы

Поиск по вопросам

четверг, 13 февраля 2020 г.

Можно ли хранить “путь” в списках и словарях в переменной?

#python #python_2x


Большой JSON читается в переменную:

json_response = json.loads(request.text)


Есть пачка методов, которые делают различные проверки различных элементов этого JSON'а

def testfoo(self, json_response):
    assertEquals(json_response['element']['some array'][0]['message'], 'foo')


def testbar(self, json_response):
    assertEquals(json_response['other element']['fizz']['buzz'], 'bar')


Вопрос: а можно ли "путь" внутри объекта хранить в переменной и передавать в метод
как аргумент? Что-то вроде этого:

def assertByPath(self, json_response, path, expected):
    assertEquals(path.get(json_response), expected)

def testfoo(self, json_response):
    foopath = path(['element']['some array'][0]['message'])
    assertByPath(json_response, path, 'foo')

def testbar(self, json_response):
    barpath = path(['other element']['fizz']['buzz'])
    assertByPath(json_response, path, 'bar')


Что-то похожее предоставляет CSS Selector.

UPD: есть даже аналогичный JSONSelect. А как насчет решения, которое работает не
только для json, а для любого сочетания вложенных списков и словарей?
    


Ответы

Ответ 1



Можно "путь" просто как список передавать: import operator def get_by_path(obj, *path): return reduce(operator.getitem, path, obj) Пример: >>> get_by_path(response, 'element', 'some array', 0, 'message') 'foo' Достоинство: позволяет в качестве ключей произвольные типы использовать. Легко другой синтаксис поддерживать, если необходимо. Например, чтобы не плодить сущности без необходимости, можно использовать подмножество языка, используемого jq утилитой (если ограничиться json типами).

Ответ 2



Ну, всегда можно навелосипедеть что-то свое: d = { "1": {2, 3}, "2": { "3": "foo" }, "3": { "3.1": { "foo": "bar" } } } def value_from_path(d, path): parts = path.split('/') value = d while parts: part = parts.pop(0) value = value[part] return value print(d['2']['3']) print(value_from_path(d, '2/3')) print(value_from_path(d, '3/3.1')) print(value_from_path(d, '3/3.1/foo')) print(value_from_path(d, '3')) Консоль: foo foo {'foo': 'bar'} bar {'3.1': {'foo': 'bar'}}

Комментариев нет:

Отправить комментарий