2016-11-20 65 views
3

我想知道如何在PyDict中的現有字段(C擴展名內)中設置新值時內存管理/引用計數的工作原理。使用PyDict_SetItemString引用計數

例如,假設創建一個字典和填充以下列方式:

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 doc文件特別提到了名單會發生什麼: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說,更換爲如何處理字典。

回答

2

舊值的參考計數由邏輯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) */ 

其減小舊值的引用計數。