gpt4 book ai didi

python - 像属性一样访问字典键?

转载 作者:IT老高 更新时间:2023-10-28 12:10:34 27 4
gpt4 key购买 nike

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

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

但是,我认为 Python 没有提供开箱即用的功能一定是有原因的。以这种方式访问​​ dict 键有什么注意事项和陷阱?

最佳答案

更新 - 2020

自从差不多十年前提出这个问题以来,Python 本身已经发生了相当大的变化。

虽然我原始答案中的方法在某些情况下仍然有效(例如,遗留项目坚持使用旧版本的 Python 以及您确实需要使用非常动态的字符串键处理字典的情况),但我认为通常 dataclasses Python 3.7 中引入的对绝大多数 AttrDict 用例的明显/正确的解决方案。

原答案

最好的方法是:

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

一些优点:

  • 它确实有效!
  • 没有字典类方法被隐藏(例如 .keys() 工作得很好。除非 - 当然 - 你为它们分配了一些值,见下文)
  • 属性和项目始终同步
  • 尝试将不存在的键作为属性正确访问会引发 AttributeError 而不是 KeyError
  • 支持 [Tab] 自动补全(例如在 jupyter 和 ipython 中)

缺点:

  • .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__() 方法,我们确保它(已经)表现得完全像字典,因为该函数调用所有 字典实例化代码。

Python 不提供开箱即用功能的一个原因

如“缺点”列表中所述,这将存储 key 的命名空间(可能来自任意和/或不受信任的数据!)与内置 dict 方法属性的命名空间结合在一起。例如:

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

关于python - 像属性一样访问字典键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4984647/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com