use*_*783 5 python oop attributes dynamic object
在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'
Run Code Online (Sandbox Code Playgroud)
同样,可以将属性添加到的实例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'
Run Code Online (Sandbox Code Playgroud)
为什么不能将成员添加到的实例list
?还是因为list
是内置类型?
更一般而言,Python中的哪些对象可以动态添加属性?
在对象上设置任意属性时,这会有效地改变 object\xe2\x80\x99s __dict__
。这__dict__
是一个存储对象所有成员的字典。所以要向对象添加成员,需要满足两个条件:
__dict__
.__dict__
需要是可变的。有多种原因可能导致其中一个条件不成立。以下类别的类型通常不允许对象修改:
\n\nint
, str
, list
, bytes
, \xe2\x80\xa6 可能是大多数(但不是全部)内置类型__slots__
. 槽位是一种明确的方式,可以__dict__
用一组固定的成员来代替它。显然,这将阻止以后添加对象(根据设计)。检测是否可以修改对象的好方法是什么?好吧,检查上面的条件。对象是否具有__dict__
:
>>> class Example:\n pass\n>>> class SlotsExample:\n __slots__ = [\'x\']\n\n>>> hasattr(Example(), \'__dict__\')\nTrue\n>>> hasattr(SlotsExample(), \'__dict__\')\nFalse\n>>> hasattr(list, \'__dict__\')\nTrue\n>>> hasattr([], \'__dict__\')\nFalse\n
Run Code Online (Sandbox Code Playgroud)\n\n以及是否__dict__
是真正的字典:
>>> isinstance(Example().__dict__, dict)\nTrue\n>>> isinstance(list.__dict__, dict)\nFalse\n
Run Code Online (Sandbox Code Playgroud)\n