搜索时正规的方式,将一些嵌套的 dicts 与普通 Python dict 转换为对象。

例如︰

>>> d = {'a': 1, 'b': {'c': 2}, 'd': ["hi", {'foo': "bar"}]}

应以这种方式可访问︰

>>> x = dict2obj(d)
>>> x.a
1
>>> x.b.c
2
>>> x.d[1].foo
bar

我认为,这是不可能不带递归,但什么都会获得 dicts objectstyle 的较好方法吗?

提前感谢您。

2009-08-20 11:28:18
问题评论:

试图执行类似最近,但定期的字典键操作 ("开始"-这是 Python 关键字) 禁止我与它经过。因为只要您试图使用"x.from"属性,您的访问将出现语法错误。

问题确实,但我可以放弃在"发件人"以使生活更容易访问大型 dict 构造:) 键入 x [] [有] [1] foo 是真正令人讨厌,因此 x.a.d[1].foo 规则。如果您需要从,您可以访问 getattr (x,从) 通过或者使用 _from 特性来代替。

而根据PEP 8 _from from_.

大部分这些"解决方案"不起作用 (甚至是接受的一个,不允许嵌套的d1.b.c),我认为很明显应使用一些从库中,如为namedtuple 集合中的,如所示此答案,...

组-使用 Python dict 对象如︰ thechangelog.com/bunch-lets-use-python-dict-like-object

回答:

更新︰在 Python 2.6,此后,请看namedtuple数据结构是否适合您的需要︰

>>> from collections import namedtuple
>>> MyStruct = namedtuple('MyStruct', 'a b d')
>>> s = MyStruct(a=1, b={'c': 2}, d=['hi'])
>>> s
MyStruct(a=1, b={'c': 2}, d=['hi'])
>>> s.a
1
>>> s.b
{'c': 2}
>>> s.c
>>> s.d
['hi']

另一种 (原答案内容) 是︰

class Struct:
    def __init__(self, **entries): 
        self.__dict__.update(entries)

然后,您可以使用︰

>>> args = {'a': 1, 'b': 2}
>>> s = Struct(**args)
>>> s
<__main__.Struct instance at 0x01D6A738>
>>> s.a
1
>>> s.b
2

+ 1 哇。不想看到的代码,我可以从我这要归功于这样的应用程序翻录。

同一个这里-,这是对于重建从面向文档数据库如 MongoDB 的 Python 对象非常有用。

若要获取更加美观打印添加︰ def repr__(self)︰ 返回 < %s > %str (' '.join('%s: 的 (k、 repr(v)) 为 (k、 v) 中 self.__dict.iteritems()))

将此项工作与嵌套词典吗?然后,dicts 包含的对象和/或列表等。是否有任何挂钩?

-1) 它不能用于嵌套的 dicts,为清楚地提出问题和 b) 相同的功能目前由于存在在argparse.Namespace (其中还定义了__eq____ne____contains__).

class obj(object):
    def __init__(self, d):
        for a, b in d.items():
            if isinstance(b, (list, tuple)):
               setattr(self, a, [obj(x) if isinstance(x, dict) else x for x in b])
            else:
               setattr(self, a, obj(b) if isinstance(b, dict) else b)

>>> d = {'a': 1, 'b': {'c': 2}, 'd': ["hi", {'foo': "bar"}]}
>>> x = obj(d)
>>> x.b.c
2
>>> x.d[1].foo
'bar'

很好 !我将替换.items().iteritems(),不过,对于较小的内存需求量。

如果没有操作的要求,这不是问题-但请注意这不会以递归方式处理对象的列表中的列表中。

我意识到这安排是旧的答案,但这些天它会更好一些,而不是丑陋该行使用抽象基类if isinstance(b, (list, tuple)):

提示︰ 有继承argparse.Namespace的其他功能,如可读的字符串表示形式。

这取决于使用的情况下,通常我们会检查它是一个字符串键入但它一种序列类型

x = type('new_dict', (object,), d)

然后将递归添加到此,即可大功告成。

编辑是如何将实现它︰

>>> d
{'a': 1, 'b': {'c': 2}, 'd': ['hi', {'foo': 'bar'}]}
>>> def obj_dic(d):
    top = type('new', (object,), d)
    seqs = tuple, list, set, frozenset
    for i, j in d.items():
    	if isinstance(j, dict):
    	    setattr(top, i, obj_dic(j))
    	elif isinstance(j, seqs):
    	    setattr(top, i, 
    		    type(j)(obj_dic(sj) if isinstance(sj, dict) else sj for sj in j))
    	else:
    	    setattr(top, i, j)
    return top

>>> x = obj_dic(d)
>>> x.a
1
>>> x.b.c
2
>>> x.d[1].foo
'bar'

请显示如何一个可以添加到此递归。

感谢您的回答。但是,其中详述应添加递归呢?到 x?或者应该 i 实现getattr和延迟,请执行转换请求?

有关使用类型,比较可怕的答案复制功能已内置到语言数 + 1

您为什么创建类型对象并不实例化它们吗?这岂不是更符合逻辑吗?我的意思是,为什么不做top_instance = top()和返回,返回top的位置?

漂亮的"叶"数据,但这些示例很方便地留出"twigs"如xx.b返回丑陋<class '__main__.new'>

任何人谁碰巧遇到如今这个问题。在 Python 2.6 + 没有称为namedtuple,它可以为您做这的集合帮助︰

from collections import namedtuple

d_named = namedtuple('Struct', d.keys())(*d.values())

In [7]: d_named
Out[7]: Struct(a=1, b={'c': 2}, d=['hi', {'foo': 'bar'}])

In [8]: d_named.a
Out[8]: 1

这不为嵌套的 dicts.应答递归的问题

您不能修改 namedtuples。

极具无人已提到一些此库专门为了提供对 dict 对象的属性样式访问并完全什么 OP 的希望。演示︰

>>> from bunch import bunchify
>>> d = {'a': 1, 'b': {'c': 2}, 'd': ["hi", {'foo': "bar"}]}
>>> x = bunchify(d)
>>> x.a
1
>>> x.b.c
2
>>> x.d[1].foo
'bar'

Python 3 库位于https://github.com/Infinidat/munch -贷方转到 @LordZ

Python 3 兼容 (显示为 2.6-3.4),分支的组名为这么多︰ github.com/Infinidat/munch

达到最佳。没有什么超。希望它在标准库中。

组是所有这些最好的解决方案,因为它,嗯,支持多种类型的序列化并维护。很好,谢谢您。祝 python3 版本为什么不被任命为同一件事,buecause。

所以只需事先警告,束和 Attrdict 也为此问题是速度很慢。它们消耗大约 1/3 和 1/2 我请求的时间分别当他们看到在我们的应用程序中经常使用。绝对不是要忽略。详细介绍其stackoverflow.com/a/31569634/364604.

虽然这不允许对 dicts 对象的类似访问,它是通过getattr这使得内省智能 REPLs 像 IPython 中困难。

内容来源于Stack Overflow Convert Python dict to object?
请输入您的翻译

Convert Python dict to object?

确认取消