如何将嵌套的Python字典转换为对象?

674 投票
45 回答
479677 浏览
提问于 2025-04-15 13:44

我在寻找一种优雅的方法,想通过属性访问的方式来获取一些包含嵌套字典和列表的数据(也就是像JavaScript那样的对象语法)。

举个例子:

>>> 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

我觉得如果不使用递归的话,这可能是不行的,但有没有什么好的方法可以让字典看起来像对象那样?

45 个回答

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

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

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

182

令人惊讶的是,居然没有人提到过 Bunch。这个库专门用来让你用属性的方式访问字典对象,正好满足了提问者的需求。下面是一个演示:

>>> 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 - 感谢 codyzu

>>> from munch import DefaultMunch
>>> d = {'a': 1, 'b': {'c': 2}, 'd': ["hi", {'foo': "bar"}]}
>>> obj = DefaultMunch.fromDict(d)
>>> obj.b.c
2
>>> obj.a
1
>>> obj.d[1].foo
'bar'
749

更新:在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
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MyStruct' object has no attribute '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

撰写回答