python - 使用 PyDict_SetItemString 进行引用计数

标签 python python-2.7

我想知道当将新值设置到 PyDict(在 C 扩展内)内的现有字段中时,内存管理/引用计数如何工作。

例如,假设按以下方式创建和填充字典:

myPyDict = PyDict_New();
tempPyObj = PyString_FromString("Original Value");
PyDict_SetItemString(myPyDict,"fieldname",tempPyObj);
Py_DECREF(tempPyObj);

从内存和引用计数的角度来看,当有后续时会发生什么

tempPyObj = PyString_FromString("New Value");
PyDict_SetItemString(myPyDict,"fieldname",tempPyObj);
Py_DECREF(tempPyObj);

原值的引用计数是否自动递减(并且内存自动释放)?

PyList_SetItem 的文档特别提到了列表会发生什么:此函数“窃取”对项目的引用,并丢弃对列表中受影响位置已存在的项目的引用。

但是 PyDic_SetItemPyDict_SetItemString 都没有说明如何处理字典的替换。

最佳答案

旧值的引用计数通过 PyList_SetItem 函数的逻辑自动递减。 您不应该自己减少旧值。

如果您想了解详细信息,请查看 CPython 源代码,特别是 Objects/dictobject.c 文件。

1) PyDict_SetItemString()

https://github.com/python/cpython/blob/c8e7c5a/Objects/dictobject.c#L3250-L3262

它是 PyDict_SetItem() 的薄包装

2) PyDict_SetItem()

https://github.com/python/cpython/blob/c8e7c5a/Objects/dictobject.c#L1537-L1565

仍然非常简单,而且很明显,与在字典中插入/替换值相关的所有繁重工作实际上都是由 insertdict() 完成的。

3) insertdict()

https://github.com/python/cpython/blob/c8e7c5a/Objects/dictobject.c#L1097-L1186

是给我们答案的函数。在此函数中,您可以找到关键代码,尤其是调用:

 Py_XDECREF(old_value); /* which **CAN** re-enter (see issue #22653) */

这会减少旧值的引用计数。

关于python - 使用 PyDict_SetItemString 进行引用计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40700251/

相关文章:

python - 重建两个最初是 float 的(字符串连接的)数字

python - 在 Python 中排列对于 RAM 来说太大的列表

python - 删除 scrapy python 中的特殊字符

macos - 在 macOS 上的 python 2.7 上安装 rpy2

python - Pandas - 带有另一个数据框python索引列表的列

python - 带 Python 客户端的 Qt C++ SSL/TLS 服务器

python - 如何使用正则表达式仅解析 HTML 文件中的文本中的外来字符

python - ctypes:例如,正确地子类化 c_void_p 以传递和返回自定义数据类型

python-2.7 - 使用 Python requests 库将数据发布到网站

python-2.7 - 如何使用 python 2.7 在 Ubuntu 12.04 上安装 PyQt?