引用计数

本节中的函数和宏用于管理 Python 对象的引用计数。

Py_ssize_t Py_REFCNT(PyObject *o)

获取 Python 对象 o 的引用计数。

请注意,返回的值可能无法真实反映实际持有该对象的引用数量。 例如,某些对象是不朽的,具有非常高的引用计数,这并不能反映实际的引用数量。 因此,不要依赖返回值的准确性,除非值为 0 或 1。

使用 Py_SET_REFCNT() 函数来设置对象的引用计数。

在 3.10 版本中更改: Py_REFCNT() 已更改为内联静态函数。

在 3.11 版本中更改: 参数类型不再是 const PyObject*

void Py_SET_REFCNT(PyObject *o, Py_ssize_t refcnt)

将对象 o 的引用计数器设置为 refcnt

启用自由线程的 Python 构建中,如果 refcnt 大于 UINT32_MAX,则该对象将变为不朽的

此函数对不朽的对象无效。

3.9 版本新增。

在 3.12 版本中更改: 不修改不朽对象。

void Py_INCREF(PyObject *o)

表示获取对象 o 的新的强引用,表明它正在使用中,不应被销毁。

此函数对不朽的对象无效。

此函数通常用于将借用引用就地转换为强引用。可以使用 Py_NewRef() 函数来创建新的强引用

完成对象使用后,通过调用 Py_DECREF() 来释放。

该对象不能为 NULL;如果您不确定它是否不是 NULL,请使用 Py_XINCREF()

不要期望此函数会以任何方式实际修改 o。对于至少 某些对象,此函数无效。

在 3.12 版本中更改: 不修改不朽对象。

void Py_XINCREF(PyObject *o)

Py_INCREF() 类似,但对象 o 可以为 NULL,在这种情况下,此函数无效。

另请参阅 Py_XNewRef()

PyObject *Py_NewRef(PyObject *o)
自 3.10 版本起成为 稳定 ABI 的一部分。

创建对对象的新强引用:在 o 上调用 Py_INCREF() 并返回对象 o

当不再需要强引用时,应在其上调用 Py_DECREF() 以释放引用。

对象 o 不能为 NULL;如果 o 可以为 NULL,请使用 Py_XNewRef()

例如

Py_INCREF(obj);
self->attr = obj;

可以写成

self->attr = Py_NewRef(obj);

另请参阅 Py_INCREF()

3.10 版本新增。

PyObject *Py_XNewRef(PyObject *o)
自 3.10 版本起成为 稳定 ABI 的一部分。

Py_NewRef() 类似,但对象 o 可以为 NULL。

如果对象 oNULL,则函数仅返回 NULL

3.10 版本新增。

void Py_DECREF(PyObject *o)

释放对对象 o强引用,表示不再使用该引用。

此函数对不朽的对象无效。

一旦最后一个强引用被释放(即,对象的引用计数达到 0),将调用对象的类型的释放函数(该函数不能为 NULL)。

此函数通常用于在其作用域退出之前删除强引用

该对象不能为 NULL;如果您不确定它是否不是 NULL,请使用 Py_XDECREF()

不要期望此函数会以任何方式实际修改 o。对于至少 某些对象,此函数无效。

警告

释放函数可能会导致调用任意 Python 代码(例如,当具有 __del__() 方法的类实例被释放时)。虽然此类代码中的异常不会传播,但执行的代码可以自由访问所有 Python 全局变量。这意味着,从全局变量可访问的任何对象都应在调用 Py_DECREF() 之前处于一致的状态。例如,从列表中删除对象的代码应将对已删除对象的引用复制到临时变量中,更新列表数据结构,然后为临时变量调用 Py_DECREF()

在 3.12 版本中更改: 不修改不朽对象。

void Py_XDECREF(PyObject *o)

Py_DECREF() 类似,但对象 o 可以为 NULL,在这种情况下,此函数无效。Py_DECREF() 中的相同警告也适用于此处。

void Py_CLEAR(PyObject *o)

释放对象 o 的一个强引用。对象可能为 NULL,在这种情况下,宏不起作用;否则效果与 Py_DECREF() 相同,只不过参数也会被设置为 NULLPy_DECREF() 的警告不适用于传递的对象,因为该宏会小心地使用临时变量,并在释放引用之前将参数设置为 NULL

当释放可能在垃圾回收期间被遍历的对象的引用时,最好使用此宏。

在 3.12 版本中变更: 宏参数现在只会被求值一次。如果参数有副作用,这些副作用将不再重复执行。

void Py_IncRef(PyObject *o)
属于 稳定 ABI 的一部分。

表示对对象 o 获取新的强引用Py_XINCREF() 的函数版本。它可用于 Python 的运行时动态嵌入。

void Py_DecRef(PyObject *o)
属于 稳定 ABI 的一部分。

释放对象 o 的一个强引用Py_XDECREF() 的函数版本。它可用于 Python 的运行时动态嵌入。

Py_SETREF(dst, src)

宏安全地释放对象 dst强引用,并将 dst 设置为 src

Py_CLEAR() 的情况一样,“显而易见”的代码可能是致命的

Py_DECREF(dst);
dst = src;

安全的方法是

Py_SETREF(dst, src);

这样安排在释放 dst 旧值的引用 _之前_ 将 dst 设置为 src,以便作为 dst 被销毁的副作用而触发的任何代码不再认为 dst 指向一个有效的对象。

在 3.6 版本中加入。

在 3.12 版本中变更: 宏参数现在只会被求值一次。如果参数有副作用,这些副作用将不再重复执行。

Py_XSETREF(dst, src)

Py_SETREF 宏的变体,它使用 Py_XDECREF() 而不是 Py_DECREF()

在 3.6 版本中加入。

在 3.12 版本中变更: 宏参数现在只会被求值一次。如果参数有副作用,这些副作用将不再重复执行。