我发现它更方便访问字典键作为obj。foo而不是obj['foo'],所以我写了这个片段:

class AttributeDict(dict):
    def __getattr__(self, attr):
        return self[attr]
    def __setattr__(self, attr, value):
        self[attr] = value

然而,我认为一定有一些原因,Python没有提供开箱即用的功能。以这种方式访问字典键的注意事项和缺陷是什么?


当前回答

最简单的方法是定义一个类,我们称之为Namespace。在字典上使用对象dict.update()。然后,字典将被视为一个对象。

class Namespace(object):
    '''
    helps referencing object in a dictionary as dict.key instead of dict['key']
    '''
    def __init__(self, adict):
        self.__dict__.update(adict)



Person = Namespace({'name': 'ahmed',
                     'age': 30}) #--> added for edge_cls


print(Person.name)

其他回答

为了给答案增加一些变化,sci-kit learn将其实现为一串:

class Bunch(dict):                                                              
    """ Scikit Learn's container object                                         

    Dictionary-like object that exposes its keys as attributes.                 
    >>> b = Bunch(a=1, b=2)                                                     
    >>> b['b']                                                                  
    2                                                                           
    >>> b.b                                                                     
    2                                                                           
    >>> b.c = 6                                                                 
    >>> b['c']                                                                  
    6                                                                           
    """                                                                         

    def __init__(self, **kwargs):                                               
        super(Bunch, self).__init__(kwargs)                                     

    def __setattr__(self, key, value):                                          
        self[key] = value                                                       

    def __dir__(self):                                                          
        return self.keys()                                                      

    def __getattr__(self, key):                                                 
        try:                                                                    
            return self[key]                                                    
        except KeyError:                                                        
            raise AttributeError(key)                                           

    def __setstate__(self, state):                                              
        pass                       

您所需要的是获取setattr和getattr方法—getattr检查字典键,然后继续检查实际属性。setstaet是针对pickle /unpickling“bunch”的修复-如果感兴趣,请检查https://github.com/scikit-learn/scikit-learn/issues/6196

没有必要自己写 Setattr()和getattr()已经存在。

类对象的优势可能在类定义和继承中发挥作用。

由于以下原因,我对现有的选项不满意,于是我开发了MetaDict。它的行为完全类似于dict,但支持点表示法和IDE自动补全,而没有其他解决方案的缺点和潜在的名称空间冲突。所有功能和使用示例都可以在GitHub上找到(见上面的链接)。

完全披露:我是MetaDict的作者。

我在尝试其他解决方案时遇到的缺点/限制:

Addict No key autocompletion in IDE Nested key assignment cannot be turned off Newly assigned dict objects are not converted to support attribute-style key access Shadows inbuilt type Dict Prodict No key autocompletion in IDE without defining a static schema (similar to dataclass) No recursive conversion of dict objects when embedded in list or other inbuilt iterables AttrDict No key autocompletion in IDE Converts list objects to tuple behind the scenes Munch Inbuilt methods like items(), update(), etc. can be overwritten with obj.items = [1, 2, 3] No recursive conversion of dict objects when embedded in list or other inbuilt iterables EasyDict Only strings are valid keys, but dict accepts all hashable objects as keys Inbuilt methods like items(), update(), etc. can be overwritten with obj.items = [1, 2, 3] Inbuilt methods don't behave as expected: obj.pop('unknown_key', None) raises an AttributeError

您可以使用dict_to_obj https://pypi.org/project/dict-to-obj/ 它完全符合你的要求

From dict_to_obj import DictToObj
a = {
'foo': True
}
b = DictToObj(a)
b.foo
True

编辑:NeoBunch是废弃的,Munch(上面提到过)可以作为一个替代品。不过,我把这个解决方案留在这里,它可能对某些人有用。

正如Doug所指出的,有一个Bunch包,你可以使用它来实现obj。关键功能。实际上有一个更新的版本叫做

尼奥邦克·蒙克

它有一个伟大的功能,通过neobunchify函数将你的字典转换为NeoBunch对象。我经常使用Mako模板,将数据作为NeoBunch对象传递使它们更具可读性,所以如果你碰巧在你的Python程序中使用了一个普通的字典,但想要在Mako模板中使用点符号,你可以这样使用:

from mako.template import Template
from neobunch import neobunchify

mako_template = Template(filename='mako.tmpl', strict_undefined=True)
data = {'tmpl_data': [{'key1': 'value1', 'key2': 'value2'}]}
with open('out.txt', 'w') as out_file:
    out_file.write(mako_template.render(**neobunchify(data)))

Mako模板看起来像这样:

% for d in tmpl_data:
Column1     Column2
${d.key1}   ${d.key2}
% endfor