像属性一样访问字典键?
问题说明
我发现以 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 没有提供这种开箱即用的功能.以这种方式访问 dict 键有哪些注意事项和陷阱?
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?
正确答案
更新 - 2020
自从大约十年前提出这个问题以来,Python 本身发生了相当大的变化.
Update - 2020
Since this question was asked almost ten years ago, quite a bit has changed in Python itself since then.
虽然我的原始答案中的方法在某些情况下仍然有效(例如,遗留项目坚持使用旧版本的 Python 以及您确实需要使用非常动态的字符串键处理字典的情况),但我认为一般来说 <在 Python 3.7 中引入的 href="https://docs.python.org/3/library/dataclasses.html" rel="noreferrer">dataclasses 是绝大多数用例的明显/正确的解决方案AttrDict
.
While the approach in my original answer is still valid for some cases, (e.g. legacy projects stuck to older versions of Python and cases where you really need to handle dictionaries with very dynamic string keys), I think that in general the dataclasses introduced in Python 3.7 are the obvious/correct solution to vast majority of the use cases of AttrDict
.
最好的方法是:
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self
一些优点:
- 它确实有效!
- 没有隐藏字典类方法(例如
.keys()
工作得很好.除非 - 当然 - 你给它们分配一些值,见下文) - 属性和项目始终同步
- 尝试访问不存在的键作为属性正确引发
AttributeError
而不是KeyError
- 支持 [Tab] 自动完成(例如在 jupyter 和 ipython 中)
- 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 ofKeyError
- Supports [Tab] autocompletion (e.g. in jupyter & ipython)
缺点:
- 如果
.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)
andE1103(maybe-no-member)
- For the uninitiated it seems like pure magic.
- 所有 python 对象在内部将它们的属性存储在一个名为
__dict__
的字典中. - 没有要求内部字典
__dict__
需要只是一个普通的 dict",因此我们可以将dict()
的任何子类分配给内部字典. - 在我们的例子中,我们只是简单地分配我们正在实例化的
AttrDict()
实例(就像我们在__init__
中一样). - 通过调用
super()
的__init__()
方法,我们确保它(已经)表现得与字典完全一样,因为该函数调用了所有字典实例化代码.
- 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 ofdict()
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.
如缺点"中所述列表,这结合了存储键的命名空间(可能来自任意和/或不受信任的数据!)与内置 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!"
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /reply/detail/tanhcfhcig
-
YouTube API 不能在 iOS (iPhone/iPad) 工作,但在桌面浏览器工作正常?
it1352 07-30 -
iPhone,一张图像叠加到另一张图像上以创建要保存的新图像?(水印)
it1352 07-17 -
保持在后台运行的 iPhone 应用程序完全可操作
it1352 07-25 -
使用 iPhone 进行移动设备管理
it1352 07-23 -
在android同时打开手电筒和前置摄像头
it1352 09-28 -
扫描 NFC 标签时是否可以启动应用程序?
it1352 08-02 -
检查邮件是否发送成功
it1352 07-25 -
Android微调工具-删除当前选择
it1352 06-20 -
希伯来语的空格句子标记化错误
it1352 06-22 -
Android App 和三星 Galaxy S4 不兼容
it1352 07-20