2013-08-05 10 views
10

Ho un oggetto di classe Python e voglio assegnare il valore di una classe variabilePython AttributeError su __del__

class Groupclass(Workerclass): 
    """worker class""" 
    count = 0 

    def __init__(self): 
     """initialize time""" 
     Groupclass.count += 1 
     self.membercount = 0; 
     self.members = [] 

    def __del__(self): 
     """delte a worker data""" 
     Groupclass.count -= 1 


if __name__ == "__main__": 
    group1 = Groupclass() 

Questo risultato dell'esecuzione è corretto, ma c'è un messaggio di errore che dice:

Exception AttributeError: "'NoneType' object has no attribute 'count'" in <bound method Groupclass.__del__ of <__main__.Groupclass instance at 0x00BA6710>> ignored 

Qualcuno può dirmi cosa ho sbagliato?

+1

vostro 'classe di base Workerclass' sembra avere un' metodo di __del__' che sta cercando di fare qualcosa con 'CONTO', ma non l'hai fatto condividere quel metodo qui. –

+0

scusate non so che è relativo ... –

+0

Il tuo messaggio è solo un avvertimento, non è un errore. ** Qualcosa ** nel metodo '__del__' ha provato a fare qualcosa con l'attributo' count' e non è riuscito. –

risposta

13

Il metodo __del__ presuppone che la classe sia ancora presente al momento della chiamata.

Questa supposizione non è corretta. Groupclass è già stato cancellato quando il programma Python termina e ora è impostato su None.

prova se il riferimento globale per la classe esiste ancora prima:

def __del__(self): 
    if Groupclass: 
     Groupclass.count -= 1 

o utilizzare type() per ottenere il riferimento locale:

def __del__(self): 
    type(self).count -= 1 

ma faccio notare che questo significa che la semantica per count cambia se Groupclass è sottoclasse (ciascuna sottoclasse ottiene un attributo .count rispetto a solo Groupclass con un attributo .count).

Citando dalla documentazione __del__ gancio:

Warning: A causa delle precarie circostanze in cui vengono richiamati __del__() metodi, eccezioni che si verificano durante la loro esecuzione vengono ignorati, e un avvertimento viene stampato sys.stderr invece . Inoltre, quando __del__() viene richiamato in risposta a un modulo in fase di eliminazione (ad esempio, quando viene eseguita l'esecuzione del programma), altri globali a cui fa riferimento il metodo __del__() potrebbero essere già stati eliminati o in fase di rimozione (ad esempio il meccanismo di importazione chiudere). Per questo motivo, i metodi __del__() dovrebbero fare il minimo assoluto necessario per mantenere invarianti esterni. A partire dalla versione 1.5, Python garantisce che i globali il cui nome inizia con un singolo trattino basso vengano cancellati dal loro modulo prima che vengano cancellati altri globali; se nessun altro riferimento a tali globalmente esiste, ciò può aiutare a garantire che i moduli importati siano ancora disponibili nel momento in cui viene chiamato il metodo __del__().

Se si sta utilizzando Python 3, si applicano due note aggiuntive:

  • CPython 3.3 applica automaticamente un randomized hash salt ai tasti str utilizzati in un dizionario globals; ciò influisce anche sull'ordine in cui i globals vengono ripuliti, e potrebbe essere che si vede il problema solo su un po 'di delle esecuzioni.

  • CPython 3.4 non imposta più globali su None (nella maggior parte dei casi), come da Safe Object Finalization; vedi PEP 442.

+0

Grazie, sta funzionando ora. Ora la mia domanda è se voglio 'del' un oggetto' Groupclass', 'Groupclass' object o 'Groupclass' deve esistere prima che il' del' venga eseguito così sembra che la dichiarazione sia in qualche modo ridondante? –

+0

@Chandler: No, quando esiste l'interprete, i nomi globali possono essere eliminati prima delle istanze; il nome 'Groupclass' è già stato ripulito. Puoi anche usare 'type (self) .count' invece, a meno che tu non abbia sottoclassi che non hanno il proprio conteggio. –

+0

ancora non capisco bene di questo concetto ma grazie mi occuperò di questo! –

Problemi correlati