Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 嵌套字典的类对象属性访问_Python_Dictionary_Nested_Bunch - Fatal编程技术网

Python 嵌套字典的类对象属性访问

Python 嵌套字典的类对象属性访问,python,dictionary,nested,bunch,Python,Dictionary,Nested,Bunch,我正在使用一个返回嵌套字典的包。 在我的类方法中使用字典语法访问这个返回对象感觉很尴尬,而其他的都是对象语法。 搜索将我带到了bunch/neobunch包,这似乎实现了我所追求的目标。我也看到了namedtuple的建议,但它们不容易支持嵌套属性,大多数解决方案依赖于在namedtuple中使用字典进行嵌套 实现这一目标的更自然的方式是什么 data = {'a': 'aval', 'b': {'b1':{'b2a':{'b3a':'b3aval','b3b':'b3bval'},'b2b':

我正在使用一个返回嵌套字典的包。 在我的类方法中使用字典语法访问这个返回对象感觉很尴尬,而其他的都是对象语法。 搜索将我带到了bunch/neobunch包,这似乎实现了我所追求的目标。我也看到了namedtuple的建议,但它们不容易支持嵌套属性,大多数解决方案依赖于在namedtuple中使用字典进行嵌套

实现这一目标的更自然的方式是什么

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中借用的想法。有一个不同的配方,我在其他几个地方也见过。一个精彩的补充!