这个PyList_Append(列表,Py_BuildValue(...))是否泄漏?

Jam*_*mes 19 c python

这会泄漏吗?:

static PyObject* foo(PyObject* self, PyObject* args){
    PyObject* list = PyList_New(0);
    for(int i = 0; i < 100; i++)
        // leak? does PyList_Append increment ref of the temporary?
        PyList_Append(list, Py_BuildValue("i", 42)); 
    return list;
}
Run Code Online (Sandbox Code Playgroud)

虽然,我认为最好这样做,无论如何?:

static PyObject* foo(PyObject* self, PyObject* args){
    PyObect* list = PyList_New(100);
    for(int i = 0; i < 100; i++)
        PyList_SetItem(list, i, Py_BuildValue("i", 42));
    return list;
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*ach 24

PyList_Append确实增加了引用计数器,所以,是的,第一个例子会泄漏. PyList_SetItem没有,使它成为一个奇怪的例外.

第二个选项会稍微提高效率,因为列表将被分配给正确的大小,Python必须在附加项目时动态调整大小.

  • python文档在哪里找到PyList_Append会增加存储对象的引用计数?我什么都没看到. (3认同)
  • 如果我不知道列表的确切大小并且想附加而不泄漏怎么办?我应该在 PyList_Append(list, my_object) 之后 Py_DecRef(my_object) 吗?PyList_Append 是否实例化具有相同值的新对象或使用 my_object 的引用? (2认同)
  • @MichaelSoulier:默认假设是传递给 C 函数的引用是借用的,如果函数需要保存引用,它将适当地增加引用计数。PyList_Append 遵循此行为,因此其文档无需特别说明。PyList_SetItem 不遵循此行为,因此文档特别提到它窃取了对新元素的引用。 (2认同)