3

在处理 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);
}
4

2 回答 2

6

如果您预先知道列表的大小,通常可以更快地创建具有正确大小的列表并使用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,您的代码大部分都可以,只是缺少初始化 fortrio_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 对如所须。

于 2012-06-02T15:58:54.810 回答
1

PyList_Append()不会“窃取”引用,因此如果您不打算在之后使用附加值,请删除它。

另外,不要忘记PyObject*从函数中返回 a ,否则系统会认为发生了异常。

于 2012-06-02T15:58:22.673 回答