Py_INCREF / DECREF: когда - PullRequest
35 голосов
/ 11 января 2011

Правильно ли указать следующее:

  • Если объект Python создан в функции C, но функция не возвращает его, INCREF не требуется, но DECREF имеет значение.

  • [false] Если функция возвращает его, вам нужно INCREF в функции, которая получает возвращаемое значение. [/ False]

  • При назначении типизированных переменных C в качестве атрибутов, таких как double, int и т. Д., Объекту Python не требуется INCREF или DECREF.

  • Назначение объектов 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
    

РЕДАКТИРОВАТЬ: -> я могу безопасно использовать это в любой ситуации? (не столкнулся с тем, где у меня возникли проблемы)

  • dealloc объекта Python должен DECREF для каждого другого объекта Python, который он имеет в качестве атрибута, но не для атрибутов типа C.

Редактировать

Под «типом C в качестве атрибута» я имею в виду bar и baz:

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

1 Ответ

40 голосов
/ 11 января 2011

Во-первых, прочитайте это более внимательно, особенно последний абзац, 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. Я не совсем уверен, что я получаю этоно это больше вопрос, связанный с Си.Как вы добавляете int или double к объекту Python?

  4. Можете ли вы привести пример, где этот метод не будет работать?

  5. Опять же, я не уверен, когда тип C является атрибутом объекта Python.Каждый int, double, long и т. Д. Так или иначе оборачивается объектом Python.

Предостережения относительно этих ответов изложены в приведенной выше ссылке,Тебе действительно не нужно даже мое плохое объяснение после прочтения этого.Надеюсь, я уточнил и больше ничего не путал.

...