2012-11-15 26 views
31

Mi piacerebbe avere una classe figlia modificare una variabile di classe che eredita dal suo genitore.classe ereditata modifica variabile in Python

mi piacerebbe fare qualcosa sulla falsariga di:

class Parent(object): 
    foobar = ["hello"] 

class Child(Parent): 
    # This does not work 
    foobar = foobar.extend(["world"]) 

e idealmente avere:

Child.foobar = ["hello", "world"] 

avrei potuto fare:

class Child(Parent): 
    def __init__(self): 
     type(self).foobar.extend(["world"]) 

ma poi ogni volta che un'istanza di un'istanza di Child, "world" viene aggiunto all'elenco, che è indesiderato. Mi potrebbe modificare ulteriormente a:

class Child(Parent): 
    def __init__(self): 
     if type(self).foobar.count("world") < 1: 
      type(self).foobar.extend(["world"]) 

ma questo è ancora un hack perché devo istanziare un'istanza del bambino prima che funzioni.

C'è un modo migliore?

risposta

35

Supponendo che si vuole avere una lista separata nella sottoclasse, non modificare la lista della classe genitore (che sembra inutile dal momento che si può solo modificarlo in luogo, o mettere i valori attesi lì per cominciare):

class Child(Parent): 
    foobar = Parent.foobar + ['world'] 

Si noti che questo funziona indipendentemente dall'ereditarietà, che è probabilmente una buona cosa.

+1

Questo è straordinariamente brillante e semplice! Inoltre, se il valore iniziale dell'attributo child deve essere identico all'attributo padre, sarebbe utile usare 'from copy import deepcopy; foobar = deepcopy (Parent.foobar) ' – zen11625

16

Si consiglia di non utilizzare valori mutevoli nelle variabili di classe. Impostare questi valori sul esempio invece, utilizzando l'inizializzatore __init__() esempio:

class Parent(object): 
    def __init__(self): 
     self.foobar = ['Hello'] 

class Child(Parent): 
    def __init__(self): 
     super(Child, self).__init__() 
     self.foobar.append('world') 

Altrimenti ciò che accade in quella lista foobar è condivisa non solo tra le istanze, ma con le sottoclassi pure.

In ogni caso, si dovrà evitare di modificare mutables di classi genitore, anche se si fa il desiderio di condividere lo stato tra i casi attraverso una variabile di classe mutabile; solo assegnazione a un nome creerebbe una nuova variabile:

class Parent(object): 
    foobar = ['Hello'] 

class Child(Parent): 
    foobar = Parent.foobar + ['world'] 

dove si crea una variabile nuova foobar per la classe Child. Utilizzando il compito, hai creato una nuova istanza di lista e la variabile Parent.foobar non è interessata.

si prendono cura con mutables annidati in tali casi; utilizzare il modulo copy per creare copie profonde, se necessario.

Problemi correlati