2012-02-09 9 views
12

Mentre codifica una nuova classe con la spyder IDE, e l'utilizzo di pylint per verificare il risultato finale, ho incontrato i messaggi di errore (ma il il codice funziona come previsto senza errori).Pythonic: uso del __dict__ nella funzione di self .__ init__ di una classe

Contesto: nella funzione di costruzione, voglio creare nuovi membri (parecchio). Di solito, questi sono abbastanza poche per cui uso questa codifica:

class MyClass(): 
    def __init__(self): 
     self.a = ... 
     self.b = ... 

Ma in un caso di molti membri (diciamo 10), con tutto pronto per lo stesso valore iniziale (diciamo che sono tutti dict()) , ero tentato di farlo:

class MyClass(): 
    def __init__(self): 
     _vars = ["a", "b", "c", ...] 
     for _var in _vars: 
      self.__dict__[_var] = dict() 

Inoltre nella classe, mi riferivo a un membro utilizzando:

class MyClass(): 
    def my_method(self): 
     print self.c 

errore con pylint (in spyder):

Quando si utilizza pylint su questo file, ho ricevuto un messaggio di errore che dice:

MyClass.my_method: istanza di 'MyClass' non ha 'c'member .

Tuttavia, il codice viene eseguito correttamente, senza errori, vale a dire. Posso accedere al membro "c" senza problemi.

Domanda: si tratta di una codifica corretta, o dovrei evitare un metodo simile per inizializzare i membri?

+2

non sono sicuro esattamente quello che stai cercando di fare con 'MyClass', ma suona come si potrebbe investire in un' collections.defaultdict () '. Vedi http://docs.python.org/library/collections.html#collections.defaultdict.Ancora interessato a ciò che gli altri hanno da dire sulla modifica di sé .__ dict__, piuttosto che creare una variabile di istanza che sembra essere un dizionario. – Noah

+0

@Noah Grazie Noah, non conoscevo la classe defaultdict. Sembra davvero interessante! Ora sto vedendo che ho sicuramente codificato alcuni "strumenti" per il mio codice, che sono stati probabilmente creati in alcuni migliori moduli python codificati (ad esempio, ho creato una cosa semplice che sembra fare un po 'il defaultdict, anche se molto meno complesso). Molte grazie. – mhavel

risposta

16

Sì, è ragionevole aggiornare direttamente il dizionario dell'istanza. In alternativa, è possibile utilizzare setattr per aggiornare le variabili. Ho visto entrambi gli approcci utilizzati nel codice di produzione.

Con setattr non v'è alcun bisogno di toccare il dizionario dell'istanza direttamente:

class MyClass(): 
    def __init__(self): 
     for var in 'a', 'b', 'c': 
      setattr(self, var, dict()) 

Ma se si aggiorna direttamente il dizionario esempio, ci sono un paio possibili miglioramenti da considerare. Ad esempio, utilizzando vars() anziché __dict__ è un po 'più bello. Inoltre, è possibile utilizzare il metodo dict.update con argomenti chiave:

class MyClass(): 
    def __init__(self): 
     vars(self).update(a=dict(), b=dict(), c=dict()) 
+1

Grazie Raymond, la tua risposta è molto chiara e utile (almeno per me). Sembra che a questo punto stia cominciando a mancare qualche background in Python ... devo scavare in un libro o anche :) – mhavel

5

In effetti va bene, ma in genere è consigliabile evitare di scherzare direttamente con __dict__. Cosa succede se, ad esempio, vuoi mettere un setter personalizzato per un attributo del tuo oggetto più avanti lungo la strada?

Nel tuo esempio caso, si può semplicemente sostituire la riga del ciclo for con il seguente:

setattr(self, _var, dict()) 
+0

Grazie Will. Questa funzione sembra davvero utile in questo caso. Ci proverò. – mhavel

Problemi correlati