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

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

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


当前回答

一般情况下它不成立。不是所有有效的dict键都有可寻址的属性(“键”)。所以,你要小心。

Python对象基本上都是字典。所以我怀疑会有什么表现或其他惩罚。

其他回答

很抱歉再添加一个,但这一个解决了subdicts和纠正AttributeError,尽管非常简单:

class DotDict(dict):
    def __init__(self, d: dict = {}):
        super().__init__()
        for key, value in d.items():
            self[key] = DotDict(value) if type(value) is dict else value
    
    def __getattr__(self, key):
        if key in self:
            return self[key]
        raise AttributeError(key) #Set proper exception, not KeyError

    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

这不是一个“好”的答案,但我认为这是俏皮的(它不处理嵌套字典在当前形式)。简单地将dict包装在函数中:

def make_funcdict(d=None, **kwargs)
    def funcdict(d=None, **kwargs):
        if d is not None:
            funcdict.__dict__.update(d)
        funcdict.__dict__.update(kwargs)
        return funcdict.__dict__
    funcdict(d, **kwargs)
    return funcdict

现在你的语法略有不同。访问dict项就像访问属性f.key一样。要以通常的方式访问dict项(和其他dict方法),请执行f()['key'],我们可以通过使用关键字参数和/或字典调用f来方便地更新dict

例子

d = {'name':'Henry', 'age':31}
d = make_funcdict(d)
>>> for key in d():
...     print key
... 
age
name
>>> print d.name
... Henry
>>> print d.age
... 31
>>> d({'Height':'5-11'}, Job='Carpenter')
... {'age': 31, 'name': 'Henry', 'Job': 'Carpenter', 'Height': '5-11'}

就是这样。如果有人提出这种方法的优点和缺点,我会很高兴。

让我发布另一个实现,它基于Kinvais的答案,但集成了http://databio.org/posts/python_AttributeDict.html中提出的AttributeDict的思想。

这个版本的优点是它也适用于嵌套字典:

class AttrDict(dict):
    """
    A class to convert a nested Dictionary into an object with key-values
    that are accessible using attribute notation (AttrDict.attribute) instead of
    key notation (Dict["key"]). This class recursively sets Dicts to objects,
    allowing you to recurse down nested dicts (like: AttrDict.attr.attr)
    """

    # Inspired by:
    # http://stackoverflow.com/a/14620633/1551810
    # http://databio.org/posts/python_AttributeDict.html

    def __init__(self, iterable, **kwargs):
        super(AttrDict, self).__init__(iterable, **kwargs)
        for key, value in iterable.items():
            if isinstance(value, dict):
                self.__dict__[key] = AttrDict(value)
            else:
                self.__dict__[key] = value

如果使用数组表示法,则可以将所有合法字符串字符作为键的一部分。 例如,obj['!#$%^&*()_']

您可以使用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