Py_DECREF 和 PY_INCREF 的作用是什么?

问题描述 投票:14回答:3

我在看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;
}

我对引用计数的理解是零散的,希望得到任何帮助。

python python-c-api
3个回答
11
投票

在这种情况下,Py_DECREF将简单地释放用tp->alloc分配的内存。

tp->alloc 设置 ref 计数为 1。Py_DECREF 将 ref 计数从 1 减少到 0;当它发现 ref 计数为 0 时,它会调用相应的函数来释放内存 (本例中是 Noddy_dealloc)。

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

如果调用者再次返回NULL,异常就会被连锁,因此有了 "return NULL"。


9
投票

CPython垃圾回收器使用了 "引用计数",即它维护一个对象的引用列表。如果一个对象的引用计数为零,那么就意味着垃圾回收器可以安全的为这个对象重新分配空间。

因此,当我们定义 PyObjects 我们必须明确地调用 Py_INCREFPy_DECREF,分别增加和减少对象的引用计数。


0
投票

引用计数是用来管理内存的,python会记录一个对象的 "拥有引用 "的数量。当一个对象有新的 "拥有引用 "时,需要增加引用计数,当一个拥有引用结束时,需要减少引用计数。如果引用计数降到0,那么对象就会被释放。

C语言没有任何语言功能可以自动完成,所以必须手动完成。为了减少incref和decref操作的次数,python C API有 "借用 "和 "窃取 "引用的概念。一般来说,参数是借用引用,而返回值则是转移引用的所有权。但也有一些例外,例如列表和元组的例程。

tp_alloc 用一个单一的引用创建一个新的对象,并将该引用的所有权转移给你。在快乐的路径上,在完成构造过程后,你反过来将该引用的所有权转移给你的调用者。

但在不快乐的路径上,你有一个部分构造的对象需要处理掉,因此有了 Py_Decref 调用。

© www.soinside.com 2019 - 2024. All rights reserved.