处理PyList_Append时,我在Py_DECREF / INCREF上丢失了。任何人都可以对以下代码发表评论吗?
PyObject * bugmaybe(PyObject *self, PyObject *args)
{
PyObject * trio=PyList_New(0);
PyObject * trio_tmp;
PyObject * otmp = PyFloat_FromDouble(1.2);
PyList_Append(trio_tmp,otmp);
//Py_DECREF(otmp);
otmp = PyFloat_FromDouble(2.3);
PyList_Append(trio_tmp,otmp);
//Py_DECREF(otmp);
PyList_Append(trio,trio_tmp);
Py_INCREF(trio_tmp);
}
答案 0 :(得分:5)
如果您事先知道列表的大小,通常可以更快地创建具有正确大小的列表并使用PyList_SetItem()
。
您的代码完全错误,trio_tmp
未初始化。
试试这个:
PyObject * bugmaybe(PyObject *self, PyObject *args)
{
PyObject * trio=PyList_New(3);
PyObject * otmp = PyFloat_FromDouble(1.2);
PyList_SetItem(trio,0,otmp);
otmp = PyFloat_FromDouble(2.3);
PyList_SetItem(trio,1,otmp);
PyList_Append(trio,2, PyList_New(0));
return trio;
}
如果你真的想使用PyList_Append
,你的代码基本上没问题,只是错过了trio_tmp
的初始化和最后多余的Py_INCREF。
PyObject * bugmaybe(PyObject *self, PyObject *args)
{
PyObject * trio=PyList_New(0);
// trio has refcount 1
PyObject * trio_tmp = PyList_New(0);
// trio_tmp has recount 1
PyObject * otmp = PyFloat_FromDouble(1.2);
// otmp has recount 1
PyList_Append(trio_tmp,otmp);
// Append does not steal a reference, so otmp refcoun = 2
Py_DECREF(otmp);
// otmp refcount = 1, but stored in the list so the pointer var
// can be reused
otmp = PyFloat_FromDouble(2.3);
PyList_Append(trio_tmp,otmp);
Py_DECREF(otmp);
// as above
PyList_Append(trio,trio_tmp);
// decrement refcount for trio_tmp, as it has recount 2 now.
Py_DECREF(trio_tmp);
return trio;
}
上面的代码相当于:
trio = []
trio_tmp = []
otmp = 1.2
trio_tmp.append(otmp)
otmp = 2.3
trio_tmp.append(otmp)
trio.append(trio_tmp)
希望它有所帮助。主要提示是在文档中,如果它说“窃取引用”,那么函数基本上取得所有权,如果它说“新引用”然后它为你做了一个INCREF,如果没有说它可能会做一个INCREF和DECREF对根据需要。
答案 1 :(得分:1)
PyList_Append()
不会“窃取”引用,因此,如果您之后不打算使用附加值,则将其删除。
另外,不要忘记从函数返回PyObject*
,否则系统会认为发生了异常。