来自https://stackoverflow.com/a/1529099/156458
要支持任意属性分配,对象需要
__dict__
: 与对象关联的字典,其中任意属性都可以 存储。否则,就无法放置新的属性。
object
的实例不带__dict__
- 如果有的话, 在可怕的循环依赖问题之前(自__dict__
起,就像大多数人一样) 其他一切,都继承自object
;-),这会让每一个人都感到厌烦 Python中带有dict的对象,这意味着许多人的开销 每个对象当前没有或需要dict的字节数 (基本上,所有不能任意分配的对象 属性不具备或需要字典。...
当类具有
__slots__
特殊属性(字符串序列)时,class
语句(更确切地说,默认元类,type
)会不< / strong>为该类的每个实例配备__dict__
(因此具有任意属性的能力),只是一组有限的,刚性的&#34;插槽&#34; (基本上每个人都可以拥有一个对象的一个引用的位置)具有给定的名称。
如果某个对象没有__dict__
,其类必须具有__slots__
属性吗?
例如object
的实例没有__dict__
,
>>> object().__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute '__dict__'
但
>>> object.__slots__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'object' has no attribute '__slots__'
那么为什么object
没有__dict__
和object
的实例没有__slots__
属性呢?
object
的实例是否有任何属性?
有多少可能性:
__dict__
,其类别为__dict__
,但没有__slots__
__dict__
,其班级有__slots__
__dict__
,而且它的类没有__slots__
?是否可以判断一个对象是否有来自其类的__dict__
?
__slots__
,那么它没有__dict__
__slots__
,我怎么知道它是否有__dict__
?答案 0 :(得分:6)
对于用户定义的类(使用常规Python代码中的class
关键字定义),类在类上始终为__slots__
,在实例上为__dict__
,或两者都有(如果其中一个定义的槽是'__dict__'
,或者继承链中的一个用户定义的类定义__slots__
而另一个不定义,隐式创建__dict__
。因此,用户定义的类涵盖了四种可能性中的三种。
修改:更正:从技术上讲,用户定义的类could have neither;该类将使用__slots__
定义,但在定义时间之后将其删除(设置类型的机制在类定义完成后不需要__slots__
保持)。没有理智的人应该这样做,它可能有不良的副作用(未经测试的完整行为),但它是可能的。
对于内置类型,至少在CPython参考解释器中,他们极不太可能有__slots__
(如果他们这样做,那就是模拟用户定义的class,定义它实际上并不做任何有用的东西)。内置类型通常将其属性存储为原始C级别值和C级结构上的指针,可选地使用显式创建的描述符或访问器方法,这消除了__slots__
的目的,这只是一个方便的有限目的等价物用户定义的类的这种结构游戏。 __dict__
是内置类型的选择,默认情况下不启用(尽管选择加入过程相当简单;您需要在结构中的某处放置PyObject*
条目并提供偏移量它在类型定义中。)
要明确指出,__dict__
无需出现在类上,因为它出现在实例上; __slots__
是类级别,可以取消实例上的__dict__
,但不会影响类本身是否具有__dict__
;用户定义的类始终具有__dict__
,但如果您谨慎使用__slots__
,则其实例不会。
简而言之:
(Sane)用户定义的类至少有一个__dict__
(在实例上)或__slots__
(在类上),并且可以同时拥有两个。疯狂的用户定义的类可能既没有,但只有一个疯狂的开发人员会这样做。
内置类通常都没有,可能提供__dict__
,几乎从不提供__slots__
,因为它对他们毫无意义。
示例:
# Class has __slots__, instances don't have __dict__
class DictLess:
__slots__ = ()
# Instances have __dict__, class lacks __slots__
class DictOnly:
pass
# Class has __slots__, instances have __dict__ because __slots__ declares it
class SlottedDict:
__slots__ = '__dict__',
# Class has __slots__ without __dict__ slot, instances have it anyway from unslotted parent
class DictFromParent(DictOnly):
__slots__ = ()
# Complete insanity: __slots__ takes effect at class definition time, but can
# be deleted later, without changing the class behavior:
class NoSlotNoDict:
__slots__ = ()
del NoSlotNoDict.__slots__
# Instances have no __dict__, class has no __slots__ but acts like it does
# (the machinery to make it slotted isn't undone by deleting __slots__)
# Please, please don't actually do this
# Built-in type without instance __dict__ or class defined __slots__:
int().__dict__ # Raises AttributeError
int.__slots__ # Also raises AttributeError
# Built-in type that opts in to __dict__ on instances:
import functools
functools.partial(int).__dict__ # Works fine
functools.partial.__slots__ # Raises AttributeError