2010-08-24 16 views
6

Supponiamo che ci sia un programma con un paio di oggetti che ci vivono al runtime.__del__ alla fine del programma

Il metodo __del__ di ciascun oggetto viene chiamato al termine dei programmi?

Se sì ho potuto per esempio fare qualcosa di simile:

class Client: 
    __del__(self): 
    disconnect_from_server() 

risposta

7

ci sono molti potential difficulties associati all'uso __del__. Di solito, non è necessario, o la migliore idea per definirlo da soli.

Invece, se si desidera un oggetto che pulisce dopo essersi all'uscita o un'eccezione, utilizzare un context manager:

per il commento di Carl:

class Client: 
    def __exit__(self,ext_type,exc_value,traceback): 
     self.disconnect_from_server() 

with Client() as c: 
    ... 

risposta originale:

import contextlib 

class Client: 
    ... 

@contextlib.contextmanager 
def make_client(): 
    c=Client() 
    yield c 
    c.disconnect_from_server() 

with make_client() as c: 
    ... 
+1

Inoltre, è possibile definire i metodi per ottenere lo stesso risultato: http://docs.python.org/reference/datamodel.html#with-statement-context-managers – carl

+0

@carl: Grazie, l'ho dimenticato, e sarebbe più facile ... – unutbu

2

Considerare l'utilizzo di with-statement per rendere la pulizia esplicita. Con riferimenti circolari __del__ non si chiama:

class Foo: 
    def __del__(self): 
    self.p = None 
    print "deleting foo" 

a = Foo() 
b = Foo() 
a.p = b 
b.p = a 

stampe nulla.

5

ho secondo l'idea generale di utilizzare i gestori di contesto e la with dichiarazione invece di basarsi su __del__ (per le stesse ragioni si preferisce try/finally ai metodi Finalizer in Java, più uno: in Python, la presenza di __del__ metodi può rendere la raccolta cicliche non recuperabile).

Tuttavia, dato che l'obiettivo è quello di avere "un oggetto che pulisce dopo essersi all'uscita o un'eccezione", l'attuazione da parte @ ~ unutbu è non corretto:

@contextlib.contextmanager 
def make_client(): 
    c=Client() 
    yield c 
    c.disconnect_from_server() 

with make_client() as c: 
    ... 

Se un'eccezione viene generato nella parte ..., disconnect_from_server_ fa non viene chiamato (poiché l'eccezione si propaga attraverso make_client, non è presente lì, quindi lo interrompe mentre è in attesa allo yield).

La soluzione è semplice:

@contextlib.contextmanager 
def make_client(): 
    c=Client() 
    try: yield c 
    finally: c.disconnect_from_server() 

In sostanza, la dichiarazione with consente di quasi dimenticare il buon vecchio try/finally ... tranne quando si scrive i gestori di contesto con contextlib , e quindi è davvero importante ricordarlo! -)

1

Sì, l'interprete Python riordina allo spegnimento, anche chiamando il metodo __del__ di ogni oggetto (tranne gli oggetti che fanno parte di un ciclo di riferimento).

Anche se, come altri hanno fatto notare, __del__ metodi sono molto fragili e deve essere usato con cautela.

Problemi correlati