【问题标题】:Which objects in Python can have attributes added dynamically?Python 中哪些对象可以动态添加属性?
【发布时间】:2017-10-03 01:16:14
【问题描述】:

在 Python 中,我可以将属性添加到我之前定义的类 C。但是,我无法向 list 添加属性 - 生成的错误消息说明这是因为 list 是内置类型:

>>> class C: pass
...
>>> C.foo = 1
>>> C.foo
1

>>> list.foo = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'list'

同样,可以将属性添加到C 的实例,但不能添加到list 的实例。然而,在这种情况下,错误信息更加模糊:

>>> o = C()
>>> o.bar = 2
>>> o.bar
2

>>> o = []
>>> o.bar = 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'bar'

为什么我不能向list 的实例添加成员?还是因为list 是内置类型吗?

更一般地说,Python 中的哪些对象可以动态添加属性?

【问题讨论】:

  • 我猜任何不是内置类型的东西
  • 一般不是内置类型。唯一令人惊讶的是,您可以为普通函数添加属性。 Google for PEP 232。

标签: python oop object dynamic attributes


【解决方案1】:

在对象上设置任意属性时,这会有效地改变对象的__dict____dict__ 是一个存储对象所有成员的字典。所以要给对象添加成员,有两个条件:

  1. 对象需要有一个__dict__
  2. 对象的__dict__ 需要是可变的。

这些条件之一可能不成立的原因有很多。以下类别的类型通常不允许对象修改:

  • 内置的native 类型在本机代码中实现,并具有一组固定的成员,并融入其本机对象定义中。示例包括intstrlistbytes,……可能大多数(但不是全部)built-in types
  • Native 来自外部库的类型,例如 numpy 的东西。
  • 任何使用__slots__ 的Python 类。 Slots 是一种明确的方式来关闭__dict__ 并将其替换为一组固定的成员。很明显,这将阻止以后添加到对象中(按设计)。

检测是否可以修改对象的好方法是什么?好吧,从上面检查条件。对象是否有__dict__

>>> class Example:
        pass
>>> class SlotsExample:
        __slots__ = ['x']

>>> hasattr(Example(), '__dict__')
True
>>> hasattr(SlotsExample(), '__dict__')
False
>>> hasattr(list, '__dict__')
True
>>> hasattr([], '__dict__')
False

以及__dict__是否是真正的字典:

>>> isinstance(Example().__dict__, dict)
True
>>> isinstance(list.__dict__, dict)
False

【讨论】:

    【解决方案2】:

    总之,依赖__setattr__魔术方法。

    Python 属性通过__getattr____setattr__ 检索。如果您有一个没有它们的类,则应用默认值。 (插槽有点不同。)

    对于内置/扩展类型(CPython 中的HEAPTYPE),默认情况下您不能添加任何其他属性,但是您可以通过提供另一个函数来覆盖它。 (纯 Python 不可能。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-17
      • 1970-01-01
      • 1970-01-01
      • 2022-09-27
      • 2015-12-12
      • 2014-05-29
      • 2011-06-04
      • 2012-01-12
      相关资源
      最近更新 更多