您的位置:  首页 » Python » 支持循环垃圾收集 – 对象实现支持(Python教程)(参考资料)

支持循环垃圾收集

Python对检测和收集涉及循环引用的垃圾的支持需要来自对象类型的支持,对象类型是其他对象的“容器”,也可以是容器。不存储对其他对象的引用或仅存储对原子类型(如数字或字符串)的引用的类型不需要为garbagecollection提供任何显式支持.

要创建容器类型,类型对象的tp_flags字段必须包含Py_TPFLAGS_HAVE_GC并提供tp_traverse处理程序的实现。如果该类型的实例是可变的,那么tp_clear还必须提供实现.

Py_TPFLAGS_HAVE_GC
具有此标志集的类型的对象必须符合此处记录的规则。为方便起见,这些对象将被称为容器对象.

容器类型的构造函数必须符合两个规则:

  1. 必须使用PyObject_GC_New()PyObject_GC_NewVar().
  2. 一旦所有可能包含对其他容器的引用的字段都被初始化,它必须调用PyObject_GC_Track().
TYPE * PyObject_GC_New TYPE,PyTypeObject  *type
类似于PyObject_New()但是对于设置了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对象或NULLop一定不能被收藏家追踪.
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.

中移除。同样,对象的解除分配器必须符合一对类似的规则:

  1. 在引用其他容器的字段无效之前,PyObject_GC_UnTrack()必须叫.
  2. 必须使用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_traversehandler接受这种类型的函数参数:

int (*visitproc)的PyObject  *object,无效 *arg
传递给tp_traverse处理程序的访问者函数的类型。应该调用函数,使用一个对象遍历为object,将第三个参数调用到tp_traverse处理程序作为arg。ThePython核心使用多个访问者函数来实现循环垃圾检测;用户不需要写自己的访问功能.

tp_traversehandler必须具有以下类型:

int (*traverseproc) PyObject  *self,visitproc  visit,void  *arg
容器对象的遍历功能。实现必须调用visit 直接包含的每个对象的函数self,带参数visit是包含的对象和arg值传递给处理程序。visit不能使用NULL对象参数调用函数。如果visit返回一个非零值,那么该值应立即返回.

为了简化tp_traverse处理程序的编写,Py_VISIT()提供宏。为了使用这个宏,tp_traverse实现必须正确命名它的参数visitarg

void Py_VISIT PyObject  *o
如果o不是NULL,用visito参数调用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;
}

tp_clear处理程序必须是inquirytype,或NULL如果对象是不可变的

int (*inquiry) PyObject  *self
删除可能已创建参考周期的引用。不可变对象不必定义此方法,因为它们永远不能直接创建引用循环。请注意,调用此方法后对象仍必须有效(不要只调用Py_DECREF()在参考上)。如果检测到该对象涉及参考循环,则该集合将调用此方法.

发表评论

电子邮件地址不会被公开。 必填项已用*标注