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

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

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


当前回答

从另一个SO问题中,有一个很好的实现示例,可以简化现有的代码。如何:

class AttributeDict(dict):
    __slots__ = () 
    __getattr__ = dict.__getitem__
    __setattr__ = dict.__setitem__

更加简洁,并且不会为将来的__getattr__和__setattr__函数留下任何额外的麻烦空间。

其他回答

你可以从标准库中获取一个方便的容器类:

from argparse import Namespace

避免复制代码位。没有标准的字典访问,但如果你真的想要的话,很容易得到一个。argparse中的代码很简单,

class Namespace(_AttributeHolder):
    """Simple object for storing attributes.

    Implements equality by attribute names and values, and provides a simple
    string representation.
    """

    def __init__(self, **kwargs):
        for name in kwargs:
            setattr(self, name, kwargs[name])

    __hash__ = None

    def __eq__(self, other):
        return vars(self) == vars(other)

    def __ne__(self, other):
        return not (self == other)

    def __contains__(self, key):
        return key in self.__dict__

元组可以使用字典键。如何在构造中访问元组?

另外,namedtuple是一种方便的结构,可以通过属性访问提供值。

编辑: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

显然,现在有一个库- https://pypi.python.org/pypi/attrdict -实现了这个确切的功能,加上递归合并和json加载。也许值得一看。

下面是一个使用内置collection .namedtuple的不可变记录的简短示例:

def record(name, d):
    return namedtuple(name, d.keys())(**d)

还有一个用法示例:

rec = record('Model', {
    'train_op': train_op,
    'loss': loss,
})

print rec.loss(..)