2011-11-20 10 views
5
class ToBeDeleted: 
    def __init__(self, value): 
     self.value = val 

    # Whatever... 

    def __del__(self): 
     print self.value 

l = [ToBeDeleted(i) for i in range(3)] 
del l 

Questa stampa 2, 1, 0.Chiamare "del" su un elenco


  • Ora, è l'ordine degli elementi eliminati definito da qualche parte nella specifica o è specifico dell'implementazione? (o forse non capisco i meccanismi sottostanti)

  • Potrebbe l'uscita, ad esempio, essere 0, 1, 2? Mi rendo conto che l'ordine 2, 1, 0 è probabilmente eseguito per evitare la riallocazione della memoria per gli elementi durante la cancellazione, ma rimane comunque la domanda.

  • E l'ultimo - qual è la differenza tra del l e del l[:] dichiarazioni?

+3

Molto dubbio che l'ordine di chiamate al '__del __()' è specificato da nessuna parte. Non pensate nemmeno di provare a scrivere codice che si basa su un particolare ordine. –

+0

Anche se l'ordine è stato specificato, è possibile mantenere i riferimenti agli elementi della lista ovunque, quindi l'ordine in cui i metodi '__del__' vengono chiamati sarà diverso dall'ordine in cui i riferimenti vengono rimossi dall'elenco. – millimoose

risposta

8

Esecuzione del l consente di eliminare ogni riferimento all'elenco, in modo che il simbolo l sarà andato. Al contrario, l'esecuzione di del l[:] rimuove il contenuto dell'elenco, lasciando l come una lista vuota.

Il metodo __del__ è ciò che viene eseguito quando viene eliminato l'ultimo riferimento a un'istanza.

L'ordine di cancellazione non è specificato ed è specifico dell'implementazione. Quando si esegue del l, l'unica cosa che è garantita è che il conteggio dei riferimenti per l'elenco l e ciascuno dei suoi elementi diminuirà di uno.

Con pypy, non accadrà nient'altro finché non viene eseguito il garbage collector. L'ordine della rimozione dell'oggetto dipende dall'ordine in cui GC visita gli oggetti.

In cpython, l'OP era corretto nell'osservare che il decremento del riferimento si verifica da destra a sinistra. Quando si richiama del l[:] qui è il codice utilizzato per decrementare i conti: http://hg.python.org/cpython/file/2.7/Objects/listobject.c#l700. Quando del l viene richiamato, codice simile viene utilizzato per decrementare i refcounts: http://hg.python.org/cpython/file/2.7/Objects/listobject.c#l596

+1

Grazie. Ma per quanto riguarda l'ordine degli elementi eliminati? –

1
  • ordine eliminazione è specifico dell'implementazione.
  • Per la risposta al primo punto, sì, potrebbe cancellarlo in qualche altro ordine (anche gli elementi prima, casuali, qualsiasi cosa) ed evitare di riallocazioni ha poco a che fare con esso. È solo una questione di come l'implementazione sceglie di guidare i bambini. Forse l'allocatore di memoria è più felice se l'ordine di liberazione inverte l'ordine di allocazione; ma è solo una supposizione.
  • del l elimina la variabile stessa (e quindi la lista, se nient'altro la tiene), mentre del l[:] rimuove tutti gli elementi dall'elenco. Prova del l; print l.
2

Altri hanno già risposto. Aggiungerò solo ciò che ho trovato nelle fonti CPython.

La funzione list_dealloc in listobject.c di file contiene questo commento immediatamente prima ciclare su voci di elenco per diminuire la loro conta di riferimento:

/* Do it backwards, for Christian Tismer. 
     There's a simple test case where somehow this reduces 
     thrashing when a *very* large list is created and 
     immediately deleted. */ 
+0

Grande scoperta! Questa è anche una prova abbastanza forte che l'ordine di cancellazione non è specificato e potrebbe non esserlo mai. – millimoose

Problemi correlati