python 递归地将嵌套的dicts转换为嵌套的namedtuples,为您提供类似于不可变对象文字的东西

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 递归地将嵌套的dicts转换为嵌套的namedtuples,为您提供类似于不可变对象文字的东西相关的知识,希望对你有一定的参考价值。

from UserDict import IterableUserDict
import collections


__author__ = 'github.com/hangtwenty'


def tupperware(mapping):
    """ Convert mappings to 'tupperwares' recursively.

    Lets you use dicts like they're JavaScript Object Literals (~=JSON)...
    It recursively turns mappings (dictionaries) into namedtuples.
    Thus, you can cheaply create an object whose attributes are accessible
    by dotted notation (all the way down).

    Use cases:

        * Fake objects (useful for dependency injection when you're making
         fakes/stubs that are simpler than proper mocks)

        * Storing data (like fixtures) in a structured way, in Python code
        (data whose initial definition reads nicely like JSON). You could do
        this with dictionaries, but namedtuples are immutable, and their
        dotted notation can be clearer in some contexts.

    .. doctest::

        >>> t = tupperware({
        ...     'foo': 'bar',
        ...     'baz': {'qux': 'quux'},
        ...     'tito': {
        ...             'tata': 'tutu',
        ...             'totoro': 'tots',
        ...             'frobnicator': ['this', 'is', 'not', 'a', 'mapping']
        ...     }
        ... })
        >>> t # doctest: +ELLIPSIS
        Tupperware(tito=Tupperware(...), foo='bar', baz=Tupperware(qux='quux'))
        >>> t.tito # doctest: +ELLIPSIS
        Tupperware(frobnicator=[...], tata='tutu', totoro='tots')
        >>> t.tito.tata
        'tutu'
        >>> t.tito.frobnicator
        ['this', 'is', 'not', 'a', 'mapping']
        >>> t.foo
        'bar'
        >>> t.baz.qux
        'quux'


    Args:
        mapping: An object that might be a mapping. If it's a mapping, convert
        it (and all of its contents that are mappings) to namedtuples
        (called 'Tupperwares').

    Returns:
        A tupperware (a namedtuple (of namedtuples (of namedtuples (...)))).
        If argument is not a mapping, it just returns it (this enables the
        recursion).
    """

    if (isinstance(mapping, collections.Mapping) and
            not isinstance(mapping, ProtectedDict)):
        for key, value in mapping.iteritems():
            mapping[key] = tupperware(value)
        return namedtuple_from_mapping(mapping)
    return mapping


def namedtuple_from_mapping(mapping, name="Tupperware"):
    this_namedtuple_maker = collections.namedtuple(name, mapping.iterkeys())
    return this_namedtuple_maker(**mapping)


class ProtectedDict(IterableUserDict):
    """ A class that exists just to tell `tupperware` not to eat it.

    `tupperware` eats all dicts you give it, recursively; but what if you
    actually want a dictionary in there? This will stop it. Just do
    ProtectedDict({...}) or ProtectedDict(kwarg=foo).
    """


def tupperware_from_kwargs(**kwargs):
    return tupperware(kwargs)

以上是关于python 递归地将嵌套的dicts转换为嵌套的namedtuples,为您提供类似于不可变对象文字的东西的主要内容,如果未能解决你的问题,请参考以下文章

如何使用pandas.dataframe()函数转换python的嵌套dict

Python 自动将dict-list嵌套数据 转换成 带类型定义的对象

递归地将`unnest_wider()`应用于所有列,直到没有更多的嵌套列表列?

我有嵌套的dict变量列表,需要将其转换为Json对象的dict变量类型

将嵌套数组转换为嵌套 html 块的递归 php 函数

如何用Python解析多层嵌套的JSON?