Python 嵌套字典的类对象属性访问
我正在使用一个返回嵌套字典的包。 在我的类方法中使用字典语法访问这个返回对象感觉很尴尬,而其他的都是对象语法。 搜索将我带到了bunch/neobunch包,这似乎实现了我所追求的目标。我也看到了namedtuple的建议,但它们不容易支持嵌套属性,大多数解决方案依赖于在namedtuple中使用字典进行嵌套 实现这一目标的更自然的方式是什么Python 嵌套字典的类对象属性访问,python,dictionary,nested,bunch,Python,Dictionary,Nested,Bunch,我正在使用一个返回嵌套字典的包。 在我的类方法中使用字典语法访问这个返回对象感觉很尴尬,而其他的都是对象语法。 搜索将我带到了bunch/neobunch包,这似乎实现了我所追求的目标。我也看到了namedtuple的建议,但它们不容易支持嵌套属性,大多数解决方案依赖于在namedtuple中使用字典进行嵌套 实现这一目标的更自然的方式是什么 data = {'a': 'aval', 'b': {'b1':{'b2a':{'b3a':'b3aval','b3b':'b3bval'},'b2b':
data = {'a': 'aval', 'b': {'b1':{'b2a':{'b3a':'b3aval','b3b':'b3bval'},'b2b':'b2bval'}} }
print(data['b']['b1']['b2a']['b3b']) # dictionary access
# print(data.b.b1.b2a.b3b) # desired access
import neobunch
data1 = neobunch.bunchify(data)
print(data1.b.b1.b2a.b3b)
下面的类将允许您执行所需的操作:
class AttrDict(dict):
""" Dictionary subclass whose entries can be accessed like attributes
(as well as normally).
"""
def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self
@staticmethod
def from_nested_dicts(data):
""" Construct nested AttrDicts from nested dictionaries. """
if not isinstance(data, dict):
return data
else:
return AttrDict({key: AttrDict.from_nested_dict(data[key])
for key in data})
data = {
"a": "aval",
"b": {
"b1": {
"b2b": "b2bval",
"b2a": {
"b3a": "b3aval",
"b3b": "b3bval"
}
}
}
}
data1 = AttrDict.from_nested_dicts(data)
print(data1.b.b1.b2a.b3b) # -> b3bval
可以使用基于基本对象构建的简单类:
class afoo1(object):
def __init__(self, kwargs):
for name in kwargs:
val = kwargs[name]
if isinstance(val, dict):
val = afoo1(val)
setattr(self,name,val)
我借用了argparse.Namespace
定义,经过调整以允许嵌套
它将被用作
In [172]: dd={'a':'aval','b':{'b1':'bval'}}
In [173]: f=afoo1(dd)
In [174]: f
Out[174]: <__main__.afoo1 at 0xb3808ccc>
In [175]: f.a
Out[175]: 'aval'
In [176]: f.b
Out[176]: <__main__.afoo1 at 0xb380802c>
In [177]: f.b.b1
Out[177]: 'bval'
In[172]:dd={'a':'aval','b':{'b1':'bval'}
In[173]:f=afoo1(dd)
In[174]:f
出[174]:
In[175]:f.a
Out[175]:“aval”
In[176]:f.b
出[176]:
在[177]中:f.b.b1
Out[177]:“bval”
它也可以用**kwargs
(以及*args
)定义。\uuuu repr\uuuu
定义可能也不错
与其他简单对象一样,可以添加属性,例如
f.c=f
(递归定义)vars(f)
返回一个字典,尽管它不进行任何递归转换)。使用\uuuuuu setattr\uuuu
方法怎么样
类属性(dict):
... def _ugetattr _;(self,name):
... 如果名称在self中:
... 返回自我[姓名]
...
... 定义设置属性(自身、名称、值):
... self[name]=self.from\u嵌套\u dict(值)
...
... def _udelattr _;(self,name):
... 如果名称在self中:
... 德尔赛尔夫[姓名]
...
... @静力学方法
... 来自嵌套目录的定义(数据):
... “”“从嵌套字典构造嵌套属性。”“”
... 如果不存在(数据、指令):
... 返回数据
... 其他:
... 返回AttrDict({key:AttrDict.from_nested_dict(data[key]))
…用于密钥输入数据})
...
>>>ad=AttrDict()
>>>广告
{}
>>>数据={'a':'aval','b':{'b1':{'b2a':{'b3a':'b3aval','b3b':'b3bval'},'b2b':'b2bval'}}
>>>ad.data=数据
>>>广告数据
{'a':'aval','b':{'b1':{'b2a':{'b3a':'b3aval','b3b':'b3bval'},'b2b':'b2bval'}}
>>>打印(广告数据b.b1.b2a.b3b)
b3bval
基于出色的答案,您可以使AttrDict类在嵌套字典上工作,而无需显式调用from_nested_dict()函数:
class AttrDict(dict):
""" Dictionary subclass whose entries can be accessed by attributes
(as well as normally).
"""
def __init__(self, *args, **kwargs):
def from_nested_dict(data):
""" Construct nested AttrDicts from nested dictionaries. """
if not isinstance(data, dict):
return data
else:
return AttrDict({key: from_nested_dict(data[key])
for key in data})
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self
for key in self.keys():
self[key] = from_nested_dict(self[key])
json.loads
有一个有趣的参数,名为,如果所有字典值都是json可序列化的,即
导入json
从类型导入SimpleNamespace
数据={'a':'aval','b':{'b1':{'b2a':{'b3a':'b3aval','b3b':'b3bval'},'b2b':'b2bval'}}
data1=json.loads(
json.dumps(数据),object_hook=lambda d:SimpleNamespace(**d)
)
打印(数据1.b.b1.b2a.b3b)#->b3bval
如果Guido正在侦听,我认为应该使用一个recursive
参数,这样您就可以执行data1=SimpleNamespace(recursive=True,**data)
试试或者。它们都支持嵌套dict的点表示法
导入dotsi
>>>data=dotsi.fy({'a':'aval','b':{'b1':{'b2a':{'b3a':'b3aval','b3b':'b3bval'},'b2b':'b2bval'}})
>>>打印(数据b.b1.b2a.b3b)
b3bval
>>>
除了dicts中的dicts之外,Dotsi还支持dicts中列表中的dicts。注意:我是Dotsi的作者。虽然从功能的角度来看,您的类没有问题,但它可以有更好的风格。对于常规的dictionary参数,我不会使用
kwargs
,因为该参数名通常用于关键字参数,而在这个上下文中根本不适用。在kwargs.items()(或Python 2中的.iteritems()
)中,我也会使用作为名称和值,而不是在键上迭代并在下一行查找值。是的,尽管错误是从命名空间
原始中未完成编辑的结果。您能否详细说明代码工作的原因/方式?谢谢@BartKleijngeld:你不明白什么部分?我不明白字典键是如何成为data1
对象的属性的。我觉得我错过了一件非常简单的事情,但如果你能向我解释一下,我将不胜感激:)@BartKleijngeld:当然……这是一只相当奇怪的野兽。AttrDict
是一个字典子类,它将自己用作类“\uuuuu dict\uuuu
。后者是通常存储实例属性的地方,通常使用
(点)表示法引用实例属性,如obj.attr
,但由于它是一个字典,您仍然可以使用常规的[]
表示法访问它们,如obj['attr']
。这是从Javascript中借用的想法。有一个不同的配方,我在其他几个地方也见过。一个精彩的补充!