Py_INCREF / DECREF:何时

时间:2011-01-11 12:47:53

标签: python python-c-api

说明以下内容是正确的:

  • 如果在C函数中创建了Python对象,但函数没有返回它,则不需要INCREF,但DECREF是。

  • [false]如果函数确实返回了它,则需要在接收返回值的函数中INCREF。[/ false]

  • 将C类变量作为属性(如doubleint等)分配给Python对象时,不需要INCREFDECREF。< / p>

  • 将Python对象作为属性分配给其他Python对象,如下所示:

    PyObject *foo;
    foo = bar // A Python object
    tmp = self->foo;
    Py_INCREF(foo);
    self->foo = foo;
    Py_XDECREF(tmp);
    //taken from the manual, but it is unclear if this works in every situation
    

编辑: - &gt;我可以在任何情况下安全地使用它吗? (没有遇到导致我出问题的地方)

    对于作为属性的每个其他Python对象,
  • 对象的dealloc需要DECREF,而不是属于C类型的属性。

修改

'C type as a attribute'是指bar和baz:

typedef struct {
    PyObject_HEAD
    PyObject *foo;
    int bar;
    double baz;
} FooBarBaz;

1 个答案:

答案 0 :(得分:39)

首先,请仔细阅读,特别是最后一段http://docs.python.org/extending/extending.html#ownership-rules

考虑它的简单方法是考虑引用计数。

  1. 您的第一个陈述是正确的。如果你创建一个新的Python对象(比如说PyLong),那么它的引用数已经是1.如果你要返回它就没关系,但是如果你不打算返回它,它需要是Python收集的垃圾,只有GC标记为refcount = 0,因此如果你不打算返回它,你需要DECREF。

  2. 第二个陈述是错误的。如果您需要返回并创建它,请返回它。返还转让所有权。如果你在返回之前是INCREF,那么你告诉Python 也保留了副本。所以再次,如果你创建它,refcount = 1。如果你然后做INCREF然后refcount = 2。但这是你想要什么,你想用refcount = 1返回。

  3. 我不是相当确定我得到了这个,但这更多是与C相关的问题。您如何向Python对象添加intdouble

  4. 您能举例说明该方法不起作用吗?

  5. 同样,我不确定C类型何时是Python对象的属性。每个intdoublelong等都以某种方式被Python对象包装。

  6. 上述链接概述了对这些答案的警告。阅读之后你甚至不需要我的不良解释。我希望我澄清并且不要混淆。