为了支持任意属性赋值,对象需要
__dict__:与对象关联的字典,其中可以存储任意属性.否则,无处可放新属性.一个实例
object没有携带__dict__- 如果确实如此,在可怕的循环依赖问题之前(因为__dict__,像大多数其他所有东西一样,继承自object;-),这会使Python中的每个对象都带有一个dict,这意味着开销当前没有或不需要dict的每个对象的许多字节(实质上,所有没有任意可分配属性的对象都没有或不需要dict)....
当类具有
__slots__特殊属性(字符串序列),那么class语句(更准确地说,默认元类type)并没有装备有该类的每个实例__dict__(有任意属性,因此的能力),只是一个有限,具有给定名称的刚性"槽"集(基本上每个可以对一些对象保持一个引用的位置).
如果一个对象没有__dict__,它的类必须有一个__slots__属性吗?
例如,object没有的实例__dict__,
>>> object().__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute '__dict__'
Run Code Online (Sandbox Code Playgroud)
但
>>> object.__slots__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'object' has no attribute '__slots__'
Run Code Online (Sandbox Code Playgroud)
那么,为什么一个实例object没有__dict__和object有没有 __slots__属性?
一个实例object有任何属性吗?
有多少种可能性:
__dict__,它的类有__dict__但没有__slots____dict__,它的类有__slots____dict__,它的类没有__slots__?是否可以判断对象是否__dict__来自其类?
__slots__,那么它没有__dict____slots__,我怎么知道它是否有__dict__?对于用户定义的类(使用class常规Python代码中的关键字定义),类将始终包含__slots__在类,__dict__实例或两者上(如果定义了其中一个槽'__dict__',或者是继承链中的一个用户定义的类)定义__slots__,另一个不定义,__dict__隐式创建).因此,用户定义的类涵盖了四种可能性中的三种.
编辑:更正:从技术上讲,用户定义的类可能既没有 ; 该类将定义为__slots__,但在定义时间之后将其删除(设置类型的机制__slots__在类定义完成后不需要保留).没有理智的人应该这样做,它可能有不良的副作用(完整的行为未经测试),但它是可能的.
对于内置类型,至少在CPython引用解释器中,它们极不可能具有__slots__(如果它们,它将模拟用户定义的类,定义它实际上没有做任何有用的事情).内置类型通常将其属性存储为原始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
Run Code Online (Sandbox Code Playgroud)