所以,我在回答this question时玩Python,发现这是无效的:
o = object()
o.attr = 'hello'
因为AttributeError: 'object' object has no attribute 'attr'
。但是,对于从对象继承的任何类,它都是有效的:
class Sub(object):
pass
s = Sub()
s.attr = 'hello'
打印s.attr
按预期显示“hello”。为什么是这个案子?Python语言规范中有什么规定不能将属性赋给vanilla对象?
为了支持任意属性分配,一个对象需要一个
__dict__
:一个与该对象相关联的dict,其中可以存储任意属性。否则,就没有地方可以放入新的属性。一个
object
的实例不会携带一个__dict__
——如果它携带了,在可怕的循环依赖问题之前(因为dict
,和大多数其他东西一样,继承自object
;-),这将为Python中的每个对象都添加一个dict,这意味着每个当前没有或需要dict的对象都有个字节的开销(本质上,没有任意可分配属性的所有对象都没有或需要dict)。例如,使用优秀的
pympler
项目(您可以从here通过svn获得它),我们可以进行一些测量…:你不会希望每个
int
占用144字节而不是16字节,对吧?-)现在,当你创建一个类(继承自任何类)时,事情会发生变化…:
…现在添加了
__dict__
(加上一点开销),因此dint
实例可以具有任意属性,但是您为这种灵活性付出了相当大的空间代价。那么,如果您想要
int
s只使用一个one额外属性foobar
。。。?这是一种罕见的需求,但Python确实为此提供了一种特殊的机制。。。……不是像
int
那么小,小心!(甚至是两个int
,一个是self
,另一个是self.foobar
——第二个可以重新分配),但肯定比一个dint
要好得多。当类具有
__slots__
特殊属性(字符串序列)时,那么class
语句(更准确地说,默认元类type
)并没有为该类的每个实例配备__dict__
(因此也就具备了拥有任意属性的能力),只是一组有限的、严格的“槽”(基本上是放置每一个都可以包含一个对某个对象的引用)和给定的名称。作为失去灵活性的交换,每个实例获得了大量字节(可能只有当您有无数个实例到处闲逛时才有意义,但是是的用例)。
这仅仅是由于优化。
口述比较大。
在C中定义的大多数(可能所有)类都没有用于优化的指令。
如果您查看source code,您将看到有许多检查来查看对象是否有dict。
正如其他回答者所说,一个
object
没有一个__dict__
。object
是所有类型的基类,包括int
或str
。因此,由object
提供的任何东西也将成为他们的负担。即使是像可选的__dict__
这样简单的东西,对于每个值都需要一个额外的指针;这将为系统中的每个对象浪费额外的4-8字节的内存,用于非常有限的实用程序。在Python 3.3+中,您可以(而且应该)使用^{} 来代替执行伪类的实例。
相关问题 更多 >
编程相关推荐