Python non fa C++ - Raii stile ("Resource acquisizione è di inizializzazione", che significa tutto ciò che si acquista nel costruttore, si rilascia nel distruttore). In effetti, quasi no lingue oltre a C++ do C++ - RAII di stile. manager contesto di Python e with
dichiarazioni sono una diverso modo per ottenere la stessa cosa che C++ fa con Raii, e che la maggior parte altre lingue che fare con finally
dichiarazioni, guard
dichiarazioni, ecc (Python ha anche finally
, naturalmente.)
Che cosa intendi esattamente per "Quando il mio oggetto di classe esce dall'ambito"?
Gli oggetti non escono dall'ambito; riferimenti (o variabili, o nomi, qualunque cosa tu preferisca). Qualche tempo dopo che l'ultimo riferimento non rientra nello scope (per CPython, questo è immediatamente, a meno che non sia coinvolto in un ciclo di riferimento, per altre implementazioni, di solito non lo è), l'oggetto sarà raccolto in modo improprio.
Se si vuole fare un po 'di pulizia in cui gli oggetti sono garbage collection, si utilizza il metodo __del__
per questo. Ma raramente è quello che vuoi veramente. (In realtà, alcune classi hanno un metodo __del__
solo per avvertire gli utenti che si sono dimenticati di pulire, piuttosto che per pulire silenziosamente.)
Una soluzione migliore è quella di rendere Animal
stesso un manager contesto, in modo che possa gestire altri gestori di contesto o semplicemente gestire le cose in modo esplicito. Poi si può scrivere:
if True:
with Animal() as animal:
# do stuff
# now the file is closed
Ecco un esempio:
class Animal(object):
def __init__(self):
self.datafile = open("file.txt")
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.datafile.close()
def makeSound(self):
sound = self.datafile # I'll be using it later
(Basta cadere alla fine del __exit__
come questo significa che, dopo aver chiamato self.datafile.close()
, siamo riusciti a fare nulla se non ci fosse un'eccezione, o re-raise la stessa eccezione se ci fosse uno. Quindi, non c'è bisogno di scrivere nulla esplicito per realizzare questo obiettivo.)
Ma di solito, se si sta andando per trasformare una classe in un gestore di contesto, devi anche aggiungere un esplicito close
. Proprio come fanno i file. E una volta fatto ciò, non è necessario rendere Animal
in un gestore di contesto; puoi semplicemente usare closing
.