【问题标题】:Getting all attributes to appear on python's `__dict__` method让所有属性出现在 python 的 __dict__ 方法上
【发布时间】:2016-07-13 22:18:26
【问题描述】:

请考虑以下 python 示例:

In [3]: class test(object):
   ...:     attribute='3'
   ...:     def __init__(self):
   ...:         self.other='4'
   ...:         

In [4]: b=test()

In [5]: b.attribute
Out[5]: '3'

In [6]: b.__dict__
Out[6]: {'other': '4'}

为什么__dict__ 只显示"other" 属性而不显示"atribute"

我如何获得包含所有类的属性和值的字典?也就是说,我如何得到这个?

{'other': '4', 'attribute': '3'}

我的意思是使用__dict__ 或其他一些简单的方法。

PS:与this question 相关,但无法从那里获得字典。

PS2:我不是在找test.__dict__或者b.__class__.__dict__,我是在找可以当做的东西

In [3]: class test(object):
   ...:     attribute='3'
   ...:     def __init__(self):
   ...:         self.other='4'
   ...:     def _print_atr(self):
   ...:         # This should print exactly {'other': '4', 'attribute': '3'}
   ...:         print(self.__all_atr__)

In [4]: b=test()

In [5]: b.attribute
Out[5]: '3'

In [6]: b.__dict__
Out[6]: {'other': '4'}

干杯

【问题讨论】:

  • 你能详细说明你所说的 PS2 是什么意思吗?为什么您假设的__all_atr__ 不包括__init___print_atr,但它确实 包括attribute
  • @mgilson 是的,抱歉,如果不清楚,这正是它会做的。它会打印出我的例外示例:{'other': '4', 'attribute': '3'}.
  • 但是为什么?排除某些事物而不排除其他事物的规则是什么?
  • @mgilson 这个想法是将b的属性和b的类属性都视为b的属性,同时仍然保持python默认的“排除”属性以一个下划线。但也许这是一种愚蠢的开始方式。你认为我应该删除这个问题吗?
  • 不,我认为您不必删除该问题。如果您只想过滤“dunder”属性/方法,您可以轻松地从我的回答中过滤字典:d = {k: v for k, v in d.items() if not (k.startswith('__') and k.endswith('__')}。但我想也值得问为什么你想这样做。最终目标是什么?

标签: python class attributes


【解决方案1】:

attribute 不是实例属性而是类属性(可以在 mappingproxy test.__dict__ 中看到)。

如果从实例中更新attribute 的值,则可以在实例__dict__ 中获取attribute

>>> b = test()
>>> b.__dict__
{'other': '4'}
>>> b.attribute
'3'
>>> b.attribute = 5
>>> b.__dict__
{'attribute': 5, 'other': '4'}

或者保留原值与

>>> b.attribute  = b.__class__.attribute # may not be necessary

或者您可以更改类的定义并将attribute 移动到类方法之一中并通过self 将其绑定到实例。

【讨论】:

  • +1 特别提及:“如果您从实例中更新属性值,则可以在实例 dict 中获取属性”
【解决方案2】:

b.__dict__ 只是b 上的属性映射,而不是b 的类(注意__init__ 也不存在)。 b 类的属性在类的__dict__ 上。

>>> class test(object):
...   attribute = 1
...   def __init__(self):
...     self.other = 2
... 
>>> b = test()
>>> b.__dict__
{'other': 2}
>>> test.__dict__
dict_proxy({'__module__': '__main__', 'attribute': 1, '__dict__': <attribute '__dict__' of 'test' objects>, '__weakref__': <attribute '__weakref__' of 'test' objects>, '__doc__': None, '__init__': <function __init__ at 0x1030f72a8>})

如果你想要两者,你可以这样做:

d = dict(vars(type(b)))
d.update(vars(b))

(请注意,有些人更喜欢vars(b) 而不是b.__dict__)当然,这没有子类...

如果你想要子类,你需要走方法解析顺序...

d = {}
for cls in type(b).__mro__:
    d.update(vars(cls))
d.update(vars(b))

【讨论】:

  • d 上运行更新时,我得到AttributeError: 'dictproxy' object has no attribute 'update'。另外,请查看我的编辑,特别是“PS2”。
【解决方案3】:

尝试输入:

test.__dict__

它显示了一个带有“属性”的键。发生这种情况正是因为属性是类变量而不是实例变量。

【讨论】:

  • 这与b.__class__.__dict__ 相同,但这并没有太大帮助。请在大约 5 分钟后检查我的编辑
猜你喜欢
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
  • 2011-11-21
  • 1970-01-01
  • 2020-10-24
  • 2019-12-02
  • 1970-01-01
相关资源
最近更新 更多