我想知道当一个新值被设置到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
的文档专门提到了列表会发生什么:This function “steals” a reference to item and discards a reference to an item already in the list at the affected position.
但PyDic_SetItem
和PyDict_SetItemString
都没有说明如何处理词典的替换。
答案 0 :(得分:3)
旧值的引用计数由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
仍然非常简单,显然所有与dict中插入/替换值相关的繁重工作实际上都是由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) */
减少旧值的引用计数。