__del__
è un finalizzatore . Viene chiamato quando un oggetto viene sottoposto a garbage collection, il che accade ad un certo punto dopo che tutti i riferimenti all'oggetto sono stati eliminati.
In un semplice caso questo potrebbe essere subito dopo aver detto del x
o, se x
è una variabile locale, dopo che la funzione termina. In particolare, a meno che non ci siano riferimenti circolari, CPython (l'implementazione standard di Python) effettuerà immediatamente la garbage collection.
Tuttavia, questo è un dettaglio dell'implementazione di CPython. L'unica proprietà richiesta della garbage collection di Python è che accade dopo che tutti i riferimenti sono stati cancellati, quindi questo potrebbe non essere necessario accadere subito dopo e potrebbe non accadere affatto .
Inoltre , le variabili possono vivere a lungo per molte ragioni , ad esempio un'eccezione che si propaga o l'introspezione del modulo può mantenere il conteggio dei riferimenti delle variabili maggiore di 0. Inoltre, la variabile può far parte del ciclo dei riferimenti - CPython con la raccolta dei rifiuti attivata si interrompe di più , ma non tutti, tali cicli, e anche allora solo periodicamente.
Dal momento che non hai alcuna garanzia che sia eseguito, non si dovrebbe mai mettere il codice in cui devi essere eseguito __del__()
- invece, questo codice appartiene alla finally
clausola del try
blocco oa un gestore di contesto in with
un'istruzione. Tuttavia, ci sono casi d'uso validi per __del__
: ad esempio, se un oggetto fa X
riferimento Y
e mantiene anche una copia del Y
riferimento in un global cache
( cache['X -> Y'] = Y
), allora sarebbe corretto X.__del__
eliminare anche la voce della cache.
Se si sa che il distruttore fornisce (in violazione delle linee guida sopra) una pulizia necessaria, si potrebbe desiderare di chiamarlo direttamente , poiché non v'è niente di speciale come un metodo: x.__del__()
. Ovviamente dovresti farlo solo se sai che non gli dispiace essere chiamato due volte. Oppure, come ultima risorsa, puoi ridefinire questo metodo utilizzando
type(x).__del__ = my_safe_cleanup_method