访问诸如Python中的属性的dict键?

问题:

我发现更方便的访问dict键为obj.foo而不是obj['foo'],所以我写了这个代码段:

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

但是,我认为Python必须有一些原因,它不提供这个功能。以这种方式访问​​dict键的注意事项和陷阱是什么?

回答:

最好的办法是:

class AttrDict(dict):
    def __init__(self, *args, **kwargs):
        super(AttrDict, self).__init__(*args, **kwargs)
        self.__dict__ = self

一些优点:

  • 它实际上有用!
  • 没有字典类方法被遮蔽(例如.keys()工作正常)
  • 属性和项目始终保持同步
  • 尝试将不存在的密钥作为属性访问正确地引发AttributeError而不是KeyError

缺点:

  • .keys()这样的方法如果被输入的数据覆盖,就可以正常工作
  • 在Python <2.7.4 / Python3 <3.2.3中导致memory leak
  • Pylint去了香蕉与E1123(unexpected-keyword-arg)E1103(maybe-no-member)
  • 对于没有兴趣的人来说,似乎是纯粹的魔法。

关于如何工作的简短说明

  • 所有python对象都将其属性存储在名为__dict__的字典中。
  • 没有要求内部字典__dict__需要是“只是一个简单的字典”,所以我们可以将dict()的任何子类分配给内部字典。
  • 在我们的例子中,我们简单地分配我们正在实例化的AttrDict()实例(如__init__)。
  • 通过调用super()__init__()方法,我们确保它(已经)的行为完全像一个字典,因为该函数调用所有的dictionary instantiation代码。

Python不提供此功能的一个原因

如“cons”列表中所述,它将存储的键的命名空间(可能来自任意和/或不受信任的数据!)与内建dict方法属性的命名空间相结合。例如:

d = AttrDict()
d.update({'items':["jacket", "necktie", "trousers"]})
for k, v in d.items():    # TypeError: 'list' object is not callable
    print "Never reached!"

 
 
Code问答: http://codewenda.com/topics/python/
Stackoverflow: Accessing dict keys like an attribute in Python?

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

+ 8 = 13