我正在寻找一种优雅的方式来获得数据使用属性访问字典与一些嵌套的字典和列表(即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
我想,如果没有递归,这是不可能的,但是有什么更好的方法来获得字典的对象样式呢?
我正在寻找一种优雅的方式来获得数据使用属性访问字典与一些嵌套的字典和列表(即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
我想,如果没有递归,这是不可能的,但是有什么更好的方法来获得字典的对象样式呢?
当前回答
下面的代码来自这里,适用于嵌套字典和ide,如VS code能够提示现有的属性:
class Struct:
def __init__(self, **kwargs):
for key, value in kwargs.items():
if isinstance(value, dict):
self.__dict__[key] = Struct(**value)
else:
self.__dict__[key] = value
my_dict = {
'name': 'bobbyhadz',
'address': {
'country': 'Country A',
'city': 'City A',
'codes': [1, 2, 3]
},
}
obj = Struct(**my_dict)
如果您想了解如何加载YAML文件并将其转换为Python对象,请参阅以下要点。
其他回答
这个怎么样:
from functools import partial
d2o=partial(type, "d2o", ())
然后可以这样使用:
>>> o=d2o({"a" : 5, "b" : 3})
>>> print o.a
5
>>> print o.b
3
下面的代码来自这里,适用于嵌套字典和ide,如VS code能够提示现有的属性:
class Struct:
def __init__(self, **kwargs):
for key, value in kwargs.items():
if isinstance(value, dict):
self.__dict__[key] = Struct(**value)
else:
self.__dict__[key] = value
my_dict = {
'name': 'bobbyhadz',
'address': {
'country': 'Country A',
'city': 'City A',
'codes': [1, 2, 3]
},
}
obj = Struct(**my_dict)
如果您想了解如何加载YAML文件并将其转换为Python对象,请参阅以下要点。
构建我对“python:如何动态地向类添加属性?”:
class data(object):
def __init__(self,*args,**argd):
self.__dict__.update(dict(*args,**argd))
def makedata(d):
d2 = {}
for n in d:
d2[n] = trydata(d[n])
return data(d2)
def trydata(o):
if isinstance(o,dict):
return makedata(o)
elif isinstance(o,list):
return [trydata(i) for i in o]
else:
return o
在要转换的字典上调用makedata,或者根据期望的输入调用trydata,它将输出一个数据对象。
注:
如果需要更多功能,可以向trydata添加elif。 显然,如果你想要x.a ={}或类似的东西,这是行不通的。 如果您想要一个只读版本,请使用原始答案中的类数据。
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'
在@max-sirwa的代码上更新了递归数组展开
class Objectify:
def __init__(self, **kwargs):
for key, value in kwargs.items():
if isinstance(value, dict):
f = Objectify(**value)
self.__dict__.update({key: f})
elif isinstance(value, list):
t = []
for i in value:
t.append(Objectify(**i)) if isinstance(i, dict) else t.append(i)
self.__dict__.update({key: t})
else:
self.__dict__.update({key: value})