Py_DECREF和PY_INCREF的目的是什么?

时间:2014-06-27 05:40:07

标签: python python-c-api

我正在阅读教程,以便定义新类型'在python中,https://docs.python.org/2/extending/newtypes.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;
}

我对引用计数的理解是不完整的,任何帮助都会受到赞赏。

3 个答案:

答案 0 :(得分:10)

在这种情况下,Py_DECREF只会释放用tp-> alloc分配的内存。

tp-> alloc将ref count设置为1. Py_DECREF将ref count从1减少到0;因为它发现引用计数为0,它调用适当的函数来释放内存(在这种情况下为Noddy_dealloc。)

如果python C api函数返回NULL,则出现问题;通常设置一个异常(保存在全局变量中)。

如果调用者再次返回NULL,则链接异常,因此'返回NULL'。

答案 1 :(得分:6)

CPython垃圾收集器使用“引用计数”,即它维护一个对象的引用列表。如果对象的引用计数降为零,则表示垃圾收集器为该对象释放空间是安全的。

因此,当我们定义 PyObjects 时,必须明确调用 Py_INCREF Py_DECREF ,这会增加和减少对象的引用计数分别

答案 2 :(得分:0)

引用计数用于管理内存,python跟踪对象的“拥有引用”的数量。当为对象创建新的“拥有参照”时,需要增加参考计数,当拥有参照完成后,需要减少参考计数。如果引用计数降至0,则对象被释放。

C没有任何语言功能可以自动执行此操作,因此必须手动完成。为了减少incref和decref操作的数量,python C API具有“借用”和“窃取”引用的概念。通常,参数会借用引用,而返回值将转移引用的所有权。但是,也有一些例外,例如列表和元组的例程。

tp_alloc使用单个引用创建一个新对象,并将该引用的所有权转让给您。在愉快的路上,您将在完成构建过程后将该引用的所有权转移给您的呼叫者。

但是在不愉快的路径上,您需要删除一个部分构造的对象,因此需要Py_Decref调用。