Почему не удается получить getitem для вложенной структуры данных? - PullRequest
0 голосов
/ 19 октября 2018

Настройка : я хотел написать метод, который бы брал вложенный объект данных и строку пути и пытался использовать компоненты пути для разыменования местоположения внутри объекта данных.

Например, у вас был бы путь, подобный /alpha/bravo/0/charlie, и метод вернул бы data_obj['alpha']['bravo'][0]['charlie'], если бы это было определенное местоположение, или сделал бы что-то еще (сгенерировать исключение, записать предупреждение, вернуть None, что угодно)если это не так.

Попытка : я чувствовал, что, возможно, был довольно простой способ сделать это, и когда я оглянулся, я нашел этот ответ ,который предлагает объединить functools.reduce с operator.getitem, чтобы пройти сколь угодно глубокий словарь .Я хотел приспособить это, чтобы покрыть диктовку, которая могла иметь вложенные списки, поэтому я немного поиграл и обнаружил, что вложенные вызовы getitem работают нормально, но комбинация getitem и reduce приводит к запутанному типунесоответствие, как показано ниже.

Вопрос : В фрагменте кода, показанном ниже, почему вызов reduce приводит к исключению, когда другие способы выполнения вложенных вызовов не приводят?

Мое необоснованное предположение: что-то в functools или operator устанавливает идентификатор getitem, указывающий на * либо * list.__getitem__ ИЛИ dict.__getitem__, и когда его просят играть хорошос reduce он застревает на одном или другом и не может переключаться назад и вперед.

Код :

$ python3 -q
>>> data_obj = { 
...     'alpha': { 
...         'bravo': [
...             {'charlie': 1}, 
...             {'delta': 2},
...         ]
...     }
... }
>>> 
>>> node_keys = ['alpha', 'bravo', 0, 'charlie']
>>> 
>>> from functools import reduce
>>> from operator import getitem
>>> 
>>> reduce(getitem, data_obj, node_keys)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list indices must be integers or slices, not str
>>> 
>>> data_obj[node_keys[0]][node_keys[1]][node_keys[2]][node_keys[3]]
1
>>> getitem(
...     getitem(
...         getitem(
...             getitem(data_obj, node_keys[0]),
...             node_keys[1]
...         ), node_keys[2]
...     ), node_keys[3]
... )
1
>>>
>>> data_obj.__getitem__(node_keys[0])\
...         .__getitem__(node_keys[1])\
...         .__getitem__(node_keys[2])\
...         .__getitem__(node_keys[3])
1
>>>

1 Ответ

0 голосов
/ 19 октября 2018

Итак, это должно быть reduce(getitem, node_keys, data_obj)

Подпись reduce равна def reduce(function, sequence, initial=None), где initial - третий аргумент.Ваш объект является начальным.

...