问题描述
根据 Python语言文档:
所以我想知道这堂课
>>> class A: __slots__ = ('__dict__', '__weakref__')
...
>>> del A.__slots__
>>> vars(A)
mappingproxy({
'__module__': '__main__',
'__dict__': <attribute '__dict__' of 'A' objects>,
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'__doc__': None
})
与此等效:
>>> class A: pass
...
>>> vars(A)
mappingproxy({
'__module__': '__main__',
'__dict__': <attribute '__dict__' of 'A' objects>,
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'__doc__': None
})
推荐答案
如果未设置 __ slots __
属性,则默认设置为创建 __ weakref __
和 __ dict __ 插槽.
If you don’t set a __slots__
attribute, the default is to create the __weakref__
and __dict__
slots in certain conditions.
这发生在 type .__ new __()
;为类提供了描述符,以访问每个实例的内存插槽:
This happens in type.__new__()
; a class is given descriptors to access memory slots for each instance:
-
首先,通过测试
tp_dictoffset
,tp_weaklistoffset
和tp_itemsize
值.
- 如果基类尚未定义一个(
base-&t; tp_dictoffset
为0),则只能有一个__ dict __
插槽. - 如果基本类型没有定义一个(
base-&t; tp_weaklistoffset
为0)并且基本具有固定长度的实例,则只能有一个__ weakref __
插槽(base-> tp_itemsize
为0).
- You can only have a
__dict__
slot if the base class doesn’t already define one (base->tp_dictoffset
is 0). - You can only have a
__weakref__
slot if the base type doesn’t define one (base->tp_weaklistoffset
is 0) and the base has fixed-length instances (base->tp_itemsize
is 0).
然后,如果没有 __ slots __
,则将标记变量设置为实际启用要添加的插槽.
Then, if there is no __slots__
, flag variables are set to actually enable the slots being added.
type .__ new __()
实现很长,但是相关部分如下所示:
The type.__new__()
implementation is long, but the relevant section looks like this:
slots = _PyDict_GetItemIdWithError(dict, &PyId___slots__);
nslots = 0;
add_dict = 0;
add_weak = 0;
may_add_dict = base->tp_dictoffset == 0;
may_add_weak = base->tp_weaklistoffset == 0 && base->tp_itemsize == 0;
if (slots == NULL) {
if (PyErr_Occurred()) {
goto error;
}
if (may_add_dict) {
add_dict++;
}
if (may_add_weak) {
add_weak++;
}
}
else {
/* Have slots */
...
}
然后,向下放下约400行,您将找到实际创建插槽的代码:
Then, some 400 lines lower down, you'll find the code that actually creates the slots:
if (add_dict) {
if (base->tp_itemsize)
type->tp_dictoffset = -(long)sizeof(PyObject *);
else
type->tp_dictoffset = slotoffset;
slotoffset += sizeof(PyObject *);
}
if (add_weak) {
assert(!base->tp_itemsize);
type->tp_weaklistoffset = slotoffset;
slotoffset += sizeof(PyObject *);
}
扩展某些本机类型(例如 int
或 bytes
)时,您不会获得 __ weakref __
插槽,因为它们的长度可变实例(由 tp_itemsize
处理).
When extending certain native types (such as int
or bytes
) you don’t get a __weakref__
slot as they have variable-length instances (handled by tp_itemsize
).
这篇关于__dict__和__weakref__是类定义中的默认位置吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!