访问像属性一样的字典键? [英] Accessing dict keys like an attribute?

查看:83
本文介绍了访问像属性一样的字典键?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现以obj.foo而不是obj['foo']的方式访问字典键更为方便,因此我编写了以下代码段:

I find it more convenient to access dict keys as obj.foo instead of obj['foo'], so I wrote this snippet:

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

但是,我认为Python一定有某些原因没有提供开箱即用的功能.以这种方式访问​​字典键会带来哪些警告和陷阱?

However, I assume that there must be some reason that Python doesn't provide this functionality out of the box. What would be the caveats and pitfalls of accessing dict keys in this manner?

推荐答案

做到这一点的最佳方法是:

The best way to do this is:

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

一些优点:

  • 它确实有效!
  • 没有遮蔽字典类的方法(例如.keys()可以正常工作.除非-当然-您为其分配了一些值,请参见下文)
  • 属性和项目始终保持同步
  • 尝试将不存在的键作为属性正确访问会引发AttributeError而不是KeyError
  • It actually works!
  • No dictionary class methods are shadowed (e.g. .keys() work just fine. Unless - of course - you assign some value to them, see below)
  • Attributes and items are always in sync
  • Trying to access non-existent key as an attribute correctly raises AttributeError instead of KeyError

缺点:

  • .keys()之类的方法如果被传入数据覆盖,将不能正常工作
  • 在Python中导致内存泄漏. 2.7.4/Python3< 3.2.3
  • Pylint与E1123(unexpected-keyword-arg)E1103(maybe-no-member)
  • 成为香蕉
  • 对于初学者来说,这似乎是纯粹的魔术.
  • Methods like .keys() will not work just fine if they get overwritten by incoming data
  • Causes a memory leak in Python < 2.7.4 / Python3 < 3.2.3
  • Pylint goes bananas with E1123(unexpected-keyword-arg) and E1103(maybe-no-member)
  • For the uninitiated it seems like pure magic.
  • 所有python对象在内部将其属性存储在名为__dict__的字典中.
  • 不要求内部字典__dict__必须是仅是简单的字典",因此我们可以将dict()的任何子类分配给内部字典.
  • 在本例中,我们仅分配要实例化的AttrDict()实例(就像在__init__中一样).
  • 通过调用super()__init__()方法,我们确保它(已经)的行为与字典完全相同,因为该函数调用了所有 dictionary实例化代码.
  • All python objects internally store their attributes in a dictionary that is named __dict__.
  • There is no requirement that the internal dictionary __dict__ would need to be "just a plain dict", so we can assign any subclass of dict() to the internal dictionary.
  • In our case we simply assign the AttrDict() instance we are instantiating (as we are in __init__).
  • By calling super()'s __init__() method we made sure that it (already) behaves exactly like a dictionary, since that function calls all the dictionary instantiation code.

如"cons"列表中所述,这将存储键的名称空间(可能来自任意和/或不受信任的数据!)与内置dict方法属性的名称空间结合在一起.例如:

As noted in the "cons" list, this combines the namespace of stored keys (which may come from arbitrary and/or untrusted data!) with the namespace of builtin dict method attributes. For example:

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

这篇关于访问像属性一样的字典键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆