使用PyDict_SetItemString进行引用计数

Phi*_*ard 4 python python-2.7

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

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

myPyDict = PyDict_New();
tempPyObj = PyString_FromString("Original Value");
PyDict_SetItemString(myPyDict,"fieldname",tempPyObj);
Py_DECREF(tempPyObj);
Run Code Online (Sandbox Code Playgroud)

从内存和引用计数的角度来看,当后续发生

tempPyObj = PyString_FromString("New Value");
PyDict_SetItemString(myPyDict,"fieldname",tempPyObj);
Py_DECREF(tempPyObj);
Run Code Online (Sandbox Code Playgroud)

原始值的参考计数是否自动减少(并且内存自动释放)?

的文档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说字典如何处理替换,也没有说。

Tom*_*och 6

PyList_SetItem功能的逻辑自动将旧值的引用计数减1 。您不应该自己减少旧值。

如果您想了解详细信息,请查看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) */
Run Code Online (Sandbox Code Playgroud)

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