如何将嵌套的Python字典转换为对象?
我在寻找一种优雅的方法,想通过属性访问的方式来获取一些包含嵌套字典和列表的数据(也就是像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