2011-01-11 4 views
32

È una corretta nel precisando le ragioni seguenti:Py_INCREF/DECREF: Quando

  • Se un oggetto Python viene creato in una funzione C, ma la funzione non restituisce, no INCREF è necessario, ma un DECREF è.

  • [false] Se la funzione non restituirlo, si ha bisogno di INCREF, nella funzione che riceve il valore di ritorno. [/ False]

  • Quando si assegna C diversi tipi di variabili come attributi, come double, int ecc., Per l'oggetto Python, non è necessario INCREF o DECREF.

  • Assegnazione di oggetti Python come attributi ai vostri altri oggetti Python va in questo modo:

    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 
    

EDIT: -> posso tranquillamente utilizzare questo in ogni situazione? (Non hanno eseguito in uno dove mi ha causato problemi)

  • dealloc di un oggetto Python deve DECREF per ogni altro oggetto Python che ha come attributo, ma non per attributi che sono tipi C.

Modifica

Con 'di tipo C come un attributo' intendo bar e baz:

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

risposta

37

In primo luogo, leggere questo con più attenzione, in particolare l'ultimo paragrafo, http://docs.python.org/extending/extending.html#ownership-rules

Un modo semplice per pensarci è pensare ai conteggi dei riferimenti.

  1. La prima frase è corretta. Se crei un nuovo oggetto Python (ad esempio PyLong), questo ha già un conteggio di riferimento di 1. Questo va bene se hai intenzione di restituirlo ma se non lo vuoi restituire, deve essere raccolto da Python ed è contrassegnato solo per GC con refcount = 0, quindi è necessario DECREF se non si intende restituirlo.

  2. La seconda affermazione è falsa. Se hai bisogno di restituirlo e lo hai creato, basta restituirlo. Restituzione della proprietà dei trasferimenti. Se dovessi INCREF prima di tornare, allora stai dicendo a Python che hai ne stai conservando una copia. Quindi, di nuovo, se lo crei, refcount = 1. Se poi fai INCREF allora refcount = 2. Ma questo è non quello che vuoi, vuoi tornare con il conto = 1.

  3. Io non sono piuttosto sicuro che ho capito, ma questa è più una domanda correlata a C. Come si aggiunge un int o double a un oggetto Python?

  4. Puoi fare un esempio in cui tale metodo non funzionerà?

  5. Ancora una volta, non sono sicuro che un tipo C sia un attributo di un oggetto Python. Ogni int, double, long, ecc. È incluso in un modo o nell'altro da un oggetto Python.

Gli avvertimenti a queste risposte sono delineati nel link sopra. Davvero non dovresti nemmeno aver bisogno della mia povera spiegazione dopo averlo letto. Spero di aver chiarito e di non confondere di più.

+0

grazie, controllerò su quell'articolo. Per quanto riguarda la tua domanda sui tipi c come attributo, vedi la modifica che ho apportato. –

+0

Giusto, perché quegli attributi sono statici e quando la memoria viene rilasciata per FooBarBaz, anche la memoria di quegli attributi andrà bene. Ora, se questi sono puntatori, devi affrontarli durante la decostruzione (quando l'oggetto viene liberato). – milkypostman

Problemi correlati