with framework espaƱol developing python python-c-api

framework - python documentation



Py_INCREF/DECREF: Cuando (1)

Es correcto decir lo siguiente:

  • Si se crea un objeto Python en una función C, pero la función no lo devuelve, no se necesita INCREF , sino un DECREF .

  • [falso] Si la función lo devuelve, necesita INCREF , en la función que recibe el valor de retorno. [/ false]

  • Al asignar variables tipo C como atributos, como double , int , etc., al objeto Python, no se necesita INCREF o DECREF .

  • Asignar objetos Python como atributos a otros objetos de Python es como sigue:

    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

EDITAR: -> ¿Puedo usar esto de forma segura en cualquier situación? (No me he encontrado con uno donde me haya causado problemas)

  • dealloc de un objeto Python necesita DECREF para cada otro objeto Python que tenga como atributo, pero no para atributos que son tipos C.

Editar

Con ''C tipo como atributo'' quiero decir bar y baz:

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


Primero, lea esto con más cuidado, específicamente el último párrafo, http://docs.python.org/extending/extending.html#ownership-rules

Una manera fácil de pensar es pensar en los recuentos de referencia.

  1. Tu primera declaración es correcta. Si crea un nuevo objeto de Python (digamos PyLong ), entonces ya tiene un recuento de referencia de 1. Esto está bien si va a devolverlo, pero si no va a devolverlo, debe ser basura recolectada por Python y solo está marcado para GC con refcount = 0, por lo tanto, necesita DECREF si no va a devolverlo.

  2. La segunda declaración es falsa. Si necesita devolverlo y lo creó, simplemente devuélvalo. Devolución de la propiedad de las transferencias. Si tuviera que INCREF antes de regresar, le está diciendo a Python que también está reteniendo una copia. Entonces, de nuevo, si lo creas, refcount = 1. Si luego haces INCREF, refcount = 2. Pero esto no es lo que quieres, quieres volver con refcount = 1.

  3. No estoy seguro de entender esto, pero esta es más una pregunta relacionada con C. ¿Cómo se está agregando un int o double a un objeto de Python?

  4. ¿Puedes dar un ejemplo donde ese método no funcionará?

  5. Nuevamente, no estoy seguro de cuándo un tipo C es un atributo de un objeto Python. Cada int , double , long , etc. está envuelto por un objeto Python de una forma u otra.

Las advertencias a estas respuestas se describen en el enlace de arriba. Realmente no deberías necesitar mi pobre explicación después de leer eso. Espero haber aclarado y no confundir más.