支持循环垃圾收集 – 对象实现支持(Python教程)(参考资料)
支持循环垃圾收集
Python对检测和收集涉及循环引用的垃圾的支持需要来自对象类型的支持,对象类型是其他对象的“容器”,也可以是容器。不存储对其他对象的引用或仅存储对原子类型(如数字或字符串)的引用的类型不需要为garbagecollection提供任何显式支持.
要创建容器类型,类型对象的tp_flags
字段必须包含Py_TPFLAGS_HAVE_GC
并提供tp_traverse
处理程序的实现。如果该类型的实例是可变的,那么tp_clear
还必须提供实现.
Py_TPFLAGS_HAVE_GC
- 具有此标志集的类型的对象必须符合此处记录的规则。为方便起见,这些对象将被称为容器对象.
容器类型的构造函数必须符合两个规则:
- TYPE*
PyObject_GC_NewVar
( TYPE,PyTypeObject *type,Py_ssize_t size) - 类似于
PyObject_NewVar()
但是对于带有Py_TPFLAGS_HAVE_GC
旗帜的集装箱物品
- //TYPE *
PyObject_GC_Resize
( TYPE,PyVarObject *op,Py_ssize_t newsize) - 调整
PyObject_NewVar()
分配的对象的大小。失败时返回theresized对象或NULL。op一定不能被收藏家追踪.
- void
PyObject_GC_Track
( PyObject *op) - 添加对象op到由集合器跟踪的容器对象集。收集器可以在意外时间运行,因此对象在跟踪时必须无效。一旦
tp_traverse
处理程序跟随的所有字段变为有效,通常在构造函数的末端附近就应该调用它.
- void
_PyObject_GC_TRACK
( PyObject *op) PyObject_GC_Track()
分配对象的内存。它不应该用于forextension modules.从版本3.6开始不推荐使用:这个宏从Python 3.8.
中移除。同样,对象的解除分配器必须符合一对类似的规则:
- 在引用其他容器的字段无效之前,
PyObject_GC_UnTrack()
必须叫. - 必须使用
PyObject_GC_Del()
.
- 无效
PyObject_GC_Del
(无效 *op) - 使用
PyObject_GC_New()
或PyObject_GC_NewVar()
.
- void
PyObject_GC_UnTrack
释放分配给对象的内存( void *op) - 删除对象op来自集合器跟踪的容器对象集。注意
PyObject_GC_Track()
可以再次调用此对象以将其添加回跟踪对象集。解除分配器(tp_dealloc
处理程序)应该在tp_traverse
处理程序变得无效.
- void
_PyObject_GC_UNTRACK
( PyObject *op) PyObject_GC_UnTrack()
的宏版本。它不应该用于forextension modules.自版本3.6:这个宏从Python 3.8.
tp_traverse
handler接受这种类型的函数参数:
- int
(*visitproc)
(的PyObject *object,无效 *arg) - 传递给
tp_traverse
处理程序的访问者函数的类型。应该调用函数,使用一个对象遍历为object,将第三个参数调用到tp_traverse
处理程序作为arg。ThePython核心使用多个访问者函数来实现循环垃圾检测;用户不需要写自己的访问功能.
tp_traverse
handler必须具有以下类型:
- int
(*traverseproc)
( PyObject *self,visitproc visit,void *arg) - 容器对象的遍历功能。实现必须调用visit 直接包含的每个对象的函数self,带参数visit是包含的对象和arg值传递给处理程序。visit不能使用NULL对象参数调用函数。如果visit返回一个非零值,那么该值应立即返回.
为了简化tp_traverse
处理程序的编写,Py_VISIT()
提供宏。为了使用这个宏,tp_traverse
实现必须正确命名它的参数visit和arg:
- void
Py_VISIT
( PyObject *o) - 如果o不是NULL,用visit和o参数调用arg回调。如果visit返回一个非零值,则返回它。使用这个宏,
tp_traverse
handlerslook like:static int my_traverse(Noddy *self, visitproc visit, void *arg) { Py_VISIT(self->foo); Py_VISIT(self->bar); return 0; }
评论被关闭。