python - Python C API - PyDict - 是否需要对值和键进行引用计数?
问题描述
我有一些代码在内部使用 PyDict 来存储数据。用户像使用普通 python 字典一样设置数据,数据由 PyDict 对象中的 C 代码存储。我的问题是:我需要引用计数(Py_INCREF)值和键吗?只是价值?文档表明调用 PyDict_SetItem 不会窃取该值的引用。我的理解是,这意味着 PyDict 对象不对值 PyObject 负责,所以需要增加引用计数。文档中没有提到密钥 - 它是否也需要增加?
一个相关的问题涉及我的代码的释放器 - 这些引用计数需要清理 - 是否有任何“捷径”来迭代 C API 中的可迭代对象并减少所有引用,或者我需要手动迭代 PyDict 对象并逐个递减所有值(可能还有键,取决于对上述内容的响应?)
有问题的代码看起来像这样(评论中有问题):
int myobject_setitem(myobject *self, PyObject *key, PyObject *value) {
if (value) {
Py_INCREF(key); // <--- is this needed?
Py_INCREF(value);
return PyDict_SetItem(self->data, key, value);
}
/* I assume I need to look up the value so I can decrement the reference count
before removing it from the dictionary, right? */
PyObject *value = PyDict_GetItem(self->data, key);
if (!value) {
return -1;
}
int ret = PyDict_DelItem(self->data, key);
Py_DECREF(key); // <------- is this needed?
Py_DECREF(value);
return ret;
}
至于析构器/释放器,我假设我只需要手动迭代 dict 并减少值(可能还有键?),除非有更好的方法?(要清楚,我的意思是在 tp_dealloc 函数中)
解决方案
您不需要在此处执行任何引用计数处理。dict 拥有它持有的所有引用,它将管理 incref/decref 调用。您不拥有任何正在创建或销毁的引用。您也不需要调用 PyDict_GetItem。
你的释放器也是如此。您只拥有对字典本身的引用,而不是字典对其内容的引用。你只需要decref dict。dict 将处理其内容。
推荐阅读
- javascript - ajax 用 jQuery load() 替换正文
- reactjs - 对屏幕分辨率或浏览器窗口大小的变化做出反应 js 引导响应
- groovy - 非静态方法的 GroovyMock 是否具有指定的行为?
- php - 带盒式喷口出口
- python - 如何垂直打印锯齿状数组?
- php - 如何在 Laravel 的每个页面上加载我的动态菜单项?
- c++ - LLVM | 检查一个值是否有符号
- java - 方法重载它如何决定在下面的情况下调用哪个版本的重载方法
- python - Python不更新定义为计算其他两个变量的变量
- php - 函数 App\Http\Controllers\AccountsController::index() 的参数太少,通过了 0 并且在 laravel 中预期正好 1