引用计数在Python C扩展中

lon*_*lue 11 c python

我正在编写我对Python的第一个C扩展,并且对我的引用计数感到困惑.这就是我想要做的.

我在for循环中填充了一个dict:

mydict = PyDict_New();

for (...)
{
    pair = PyTuple_Pack(2, PyString_FromString("some string"),
          PyString_FromString("some other string"));

    /* at this point, the refcnt for the tuple is 1, the refcnts for the
       2 string items are 2. Because according to the source, PyString_FromString
       does an INCREF, and PyTuple_Pack() does an INCREF on its items
     */

    PyDict_SetItem(mydict, PyString_FromString("some key"), pair);

    /* At this point, the key's refcnt is 2.  PyString_FromString sets it to 1 and 
       PyDict_SetItem INCREF's it. Ditto for pair since PyDict_SetItem also INCREF's
       the value.
     */

    Py_DECREF(pair);

    /* pair's refcnt is 1 which makes sense to me since mydict now owns the tuple, 
       but the refcnt for its items are still at 2.  I don't understand this part.
     */
}

return mydict;
Run Code Online (Sandbox Code Playgroud)

我的引用是否正确?在C API文档中,它特别建议使用PyObject_FromXXX 函数作为参数PyTuple_SetItemPyList_SetItem因为它们"窃取"引用.

没有记录PyDict_SetItem抢断是否引用.我猜它不是在哪种情况下,我应该这样做

first = PyString_FromString("some string");
second = PyString_FromString("some other string");
pair = PyTuple_Pack(2, first, second);
Py_DECREF(second);
Py_DECREF(first);
Run Code Online (Sandbox Code Playgroud)

我对吗?

Nat*_*ert 6

如果您查看 PyTuple_Pack 的 CPython 源代码 (Objects/tupleobject.c),您会发现它确实增加了每个打包对象的引用计数。如果您改为执行 PyTuple_New 后跟 PyTuple_SetItem 调用,您将不需要减少引用计数,因为 SetItem 窃取了引用。

最后,您可能只想使用 Py_BuildValue("(ss)", "some string", "some other string"); 它将为您构建元组,并为您创建 PyStrings:http : //docs.python.org/c-api/arg.html#Py_BuildValue