python - __dict__ 和 __weakref__ 是类定义中的默认插槽吗?
问题描述
根据Python 语言文档:
__slots__
允许我们显式声明数据成员(如属性)并拒绝创建__dict__
and__weakref__
(除非__slots__
在父级中显式声明或可用。)
所以我想知道这门课是否
>>> 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__
插槽。
这发生在type.__new__()
;一个类被赋予描述符来访问每个实例的内存槽:
首先,通过测试类型对象结构中的,和值来检查该类型是否可以具有这些插槽。
tp_dictoffset
tp_weaklistoffset
tp_itemsize
__dict__
如果基类尚未定义一个(base->tp_dictoffset
为 0),则只能有一个插槽。__weakref__
如果基本类型未定义一个(base->tp_weaklistoffset
为 0)并且基本类型具有固定长度的实例(为 0),则您只能拥有一个插槽base->tp_itemsize
。
然后,如果没有
__slots__
,则设置标志变量以实际启用正在添加的插槽。
type.__new__()
实现很长,但相关部分如下所示:
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 行,您将找到实际创建插槽的代码:
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
or bytes
)时,您不会获得__weakref__
插槽,因为它们具有可变长度实例(由 处理tp_itemsize
)。
推荐阅读
- python - “导入模块”和“从模块导入 *”有什么区别
- qt - UIC 生成的头文件无法识别包含自定义小部件头的路径
- node.js - 如何检查 json 数组是否包含 Nodejs 中的重复值?
- r - 缩放或移动地图后以 png 格式导出传单
- java - 在 Java 中为 TreeSet 创建新的比较器
- regex - Codemirror simplemode 插件为函数创建正则表达式
- powerbi - 有没有办法在电源查询代码中使用 if exists 语句?
- amazon-web-services - 无法将 RDS 数据库连接到 Lambda 函数(使用无服务器框架)
- java - 使用 editText gettext 更改 Android 操作栏标题文本
- javascript - 搜索脚本的问题我无法从导航栏获取良好的属性到 vue.js 中的 searchcomponent