我在看python中定义 "新类型 "的教程,请问Py_DECREF和PY_INCREF有什么作用? https:/docs.python.org2extendingnewtypes.html。我不明白在这段代码中使用Py_DECREF的目的。
static PyObject *
Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
Noddy *self;
self = (Noddy *)type->tp_alloc(type, 0);
if (self != NULL) {
self->first = PyString_FromString("");
if (self->first == NULL)
{
Py_DECREF(self);
return NULL;
}
self->last = PyString_FromString("");
if (self->last == NULL)
{
Py_DECREF(self);
return NULL;
}
self->number = 0;
}
return (PyObject *)self;
}
我对引用计数的理解是零散的,希望得到任何帮助。
在这种情况下,Py_DECREF将简单地释放用tp->alloc分配的内存。
tp->alloc 设置 ref 计数为 1。Py_DECREF 将 ref 计数从 1 减少到 0;当它发现 ref 计数为 0 时,它会调用相应的函数来释放内存 (本例中是 Noddy_dealloc)。
如果一个python C api函数返回NULL,说明出了问题;通常会设置一个异常(保存在全局变量中)。
如果调用者再次返回NULL,异常就会被连锁,因此有了 "return NULL"。
CPython垃圾回收器使用了 "引用计数",即它维护一个对象的引用列表。如果一个对象的引用计数为零,那么就意味着垃圾回收器可以安全的为这个对象重新分配空间。
因此,当我们定义 PyObjects 我们必须明确地调用 Py_INCREF 和 Py_DECREF,分别增加和减少对象的引用计数。
引用计数是用来管理内存的,python会记录一个对象的 "拥有引用 "的数量。当一个对象有新的 "拥有引用 "时,需要增加引用计数,当一个拥有引用结束时,需要减少引用计数。如果引用计数降到0,那么对象就会被释放。
C语言没有任何语言功能可以自动完成,所以必须手动完成。为了减少incref和decref操作的次数,python C API有 "借用 "和 "窃取 "引用的概念。一般来说,参数是借用引用,而返回值则是转移引用的所有权。但也有一些例外,例如列表和元组的例程。
tp_alloc 用一个单一的引用创建一个新的对象,并将该引用的所有权转移给你。在快乐的路径上,在完成构造过程后,你反过来将该引用的所有权转移给你的调用者。
但在不快乐的路径上,你有一个部分构造的对象需要处理掉,因此有了 Py_Decref 调用。