为啥不能在 python 中为对象添加属性? [复制]

Posted

技术标签:

【中文标题】为啥不能在 python 中为对象添加属性? [复制]【英文标题】:Why can't you add attributes to object in python? [duplicate]为什么不能在 python 中为对象添加属性? [复制] 【发布时间】:2010-11-20 02:14:40 【问题描述】:

(用 Python shell 编写)

>>> o = object()
>>> o.test = 1

Traceback (most recent call last):
  File "<pyshell#45>", line 1, in <module>
    o.test = 1
AttributeError: 'object' object has no attribute 'test'
>>> class test1:
    pass

>>> t = test1()
>>> t.test

Traceback (most recent call last):
  File "<pyshell#50>", line 1, in <module>
    t.test
AttributeError: test1 instance has no attribute 'test'
>>> t.test = 1
>>> t.test
1
>>> class test2(object):
    pass

>>> t = test2()
>>> t.test = 1
>>> t.test
1
>>> 

为什么对象不允许你给它添加属性?

【问题讨论】:

【参考方案1】:

注意object 实例没有__dict__ 属性:

>>> dir(object())
['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']

在派生类中说明此行为的示例:

>>> class Foo(object):
...     __slots__ = 
...
>>> f = Foo()
>>> f.bar = 42
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'bar'

引用slots 上的文档:

[...] __slots__ 声明采用一系列实例变量,并在每个实例中保留足够的空间来保存每个变量的值。节省空间是因为 __dict__ 不是为每个实例创建的。

编辑:为了回答 cmets 的 ThomasH,OP 的测试类是一个“旧式”类。试试:

>>> class test: pass
...
>>> getattr(test(), '__dict__')

>>> getattr(object(), '__dict__')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute '__dict__'

您会注意到有一个__dict__ 实例。对象类可能没有定义__slots__,但结果是一样的:缺少__dict__,这是阻止动态分配属性的原因。我已经重新组织了我的答案以使其更清晰(将第二段移到顶部)。

【讨论】:

所以,您是说 object 类以一种或另一种方式使用 __slots__ 以防止分配实例成员。这是一个假设还是一个事实(即它是否在 object 的实现中)?因为 object 实例中仅仅缺少 __\dict__ 并不具有指示性。 OP 的 test1 类的实例在使用 dir() 调用时显示相同的缺失 __dict__,但仍然允许分配实例成员。 @ThomasH,请参阅我添加到答案中的注释。【参考方案2】:

好问题,我猜这与object 是一个内置/扩展类型这一事实有关。

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

IIRC,这与 __dict__ 属性的存在有关,或者更准确地说,当对象没有 __dict__ 属性时,setattr() 会爆炸。

【讨论】:

以上是关于为啥不能在 python 中为对象添加属性? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能在继承属性中为封闭的泛型使用 C# 语法,但 CLR 语法很好

为啥我不能在 VS2019 中为对话框添加 Class?

OC为啥 Category不能添加属性

js 对象中为啥不能直接调用自己的属性方法?

为啥允许向已经实例化的对象添加属性?

如何在node.js中为对象动态添加属性?