Использование ключей JSON в качестве атрибутов во вложенном JSON

Я работаю с вложенными структурами данных, подобными JSON, в Python 2.7, которые я обмениваю с некоторым чужим кодом Perl. Я просто хочу «работать» с этими вложенными структурами списков и словарей более питоническим способом.

Итак, если у меня есть структура, подобная этой...

a = {
    'x': 4,
    'y': [2, 3, { 'a': 55, 'b': 66 }],
}

...я хочу иметь возможность работать с ней в сценарии Python, как если бы это были вложенные классы/структуры Python, например:

>>> aa = j2p(a)  # <<- this is what I'm after.
>>> print aa.x
4
>>> aa.z = 99
>>> print a
{
    'x': 4,
    'y': [2, 3, { 'a': 55, 'b': 66 }],
    'z': 99
}

>>> aa.y[2].b = 999

>>> print a
{
    'x': 4,
    'y': [2, 3, { 'a': 55, 'b': 999 }],
    'z': 99
}

Таким образом aa является прокси в исходной структуре. Это то, к чему я пришел на данный момент, вдохновленный превосходным вопросом Что такое метакласс в Python?.

def j2p(x):
    """j2p creates a pythonic interface to nested arrays and
    dictionaries, as returned by json readers.

    >>> a = { 'x':[5,8], 'y':5}
    >>> aa = j2p(a)
    >>> aa.y=7
    >>> print a
    {'x': [5, 8], 'y':7}
    >>> aa.x[1]=99
    >>> print a
    {'x': [5, 99], 'y':7}

    >>> aa.x[0] = {'g':5, 'h':9}
    >>> print a
    {'x': [ {'g':5, 'h':9} , 99], 'y':7}
    >>> print aa.x[0].g
    5
    """
    if isinstance(x, list):
        return _list_proxy(x)
    elif isinstance(x, dict):
        return _dict_proxy(x)
    else:
        return x

class _list_proxy(object):
    def __init__(self, proxied_list):
        object.__setattr__(self, 'data', proxied_list)
    def __getitem__(self, a):
        return j2p(object.__getattribute__(self, 'data').__getitem__(a))
    def __setitem__(self, a, v):
        return object.__getattribute__(self, 'data').__setitem__(a, v)


class _dict_proxy(_list_proxy):
    def __init__(self, proxied_dict):
        _list_proxy.__init__(self, proxied_dict)
    def __getattribute__(self, a):
        return j2p(object.__getattribute__(self, 'data').__getitem__(a))
    def __setattr__(self, a, v):
        return object.__getattribute__(self, 'data').__setitem__(a, v)


def p2j(x):
    """p2j gives back the underlying json-ic json-ic nested
    dictionary/list structure of an object or attribute created with
    j2p.
    """
    if isinstance(x, (_list_proxy, _dict_proxy)):
        return object.__getattribute__(x, 'data')
    else:
        return x

Теперь мне интересно, существует ли элегантный способ отображения всего набора специальных функций __*__, таких как __iter__, __delitem__? поэтому мне не нужно разворачивать вещи, используя p2j()просто для повторения или других питонических вещей.

# today:
for i in p2j(aa.y):
     print i
# would like to...
for i in aa.y:
     print i

8
задан martineau 21 February 2018 в 16:34
поделиться