2016-06-26 90 views
1

我正在使用一个返回嵌套字典的包。 当我的类方法以字典语法访问此返回对象时,当其他所有内容都处于对象语法中时,感觉很尴尬。 搜索带来了一堆/ neobunch包,这似乎实现了我后。我还看到了命名建议,但这些并不轻易支持嵌套属性,大多数解决方案都依赖于在名称中使用字典进行嵌套。嵌套字典的对象状属性访问

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

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) 

回答

2

下面的类将让你做你想要的:

class AttrDict(dict): 
    """ Dictionary subclass whose entries can be accessed by attributes 
     (as well as normally). 
    """ 
    def __init__(self, *args, **kwargs): 
     super(AttrDict, self).__init__(*args, **kwargs) 
     self.__dict__ = self 

    @staticmethod 
    def from_nested_dict(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_dict(data) 
print(data1.b.b1.b2a.b3b) # -> b3bval 
+0

请您详细说明为什么/代码如何工作?谢谢! –

+0

@BartKleijngeld:你不了解哪些部分? – martineau

+0

我不明白字典键如何成为'data1'对象的属性。我觉得我错过了一些非常简单的东西,但如果你能向我解释那部分内容,我将不胜感激:)。 –

0

一个简单的类,构建了基本对象可用于:

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' 

它也已经与**kwargs定义(连同*args)它会被使用。 A __repr__的定义也可能很好。

与其他简单对象一样,可以添加属性,例如, f.c = f(递归定义)。 vars(f)返回一个字典,尽管它没有做任何递归转换)。

+0

从功能的角度来看,你的课没有什么问题,但它可以有更好的风格。我不会使用'kwargs'作为常规字典参数,因为参数名通常用于关键字参数,在此上下文中根本不适用。我还会在Python 2中使用'for name,value in kwargs.items()'(或'.iteritems()'),而不是迭代键并在下一行查找值。 – Blckknght

+0

是的,虽然错误是由来自'命名空间'原始的不完整编辑造成的。 – hpaulj