2011-12-14 23 views
5

Vorrei memorizzare alcune informazioni su una classe come variabili di classe (statiche). Tuttavia, non riesco a capire come queste cose vengano inizializzate. Ecco un semplice, ad esempio stupido:Inizializzazione variabile classe Python

class A(object): 
    clsVar = 'a' 
    @classmethod 
    def clsMeth(cls): 
     print 'changing clsVar' 
     cls.clsVar = 'b' 
    A.clsMeth() 
# prints 'changing clsVar' 

print A.clsVar # prints 'a' 
A.clsVar = 'b' 
print A.clsVar # prints 'b' 

Poiché la funzione stato chiamato (come l'istruzione print ha lavorato), perché non la permanenza variabile di classe è cambiato? Devo usare un metaclasse se non voglio farlo dopo che la definizione della classe è completa?

[In particolare, voglio che clsMeth sia un decoratore e che la variabile di classe sia un elenco di tutte le funzioni che sono state così decorate. Immagino che questo non sia il modo giusto per realizzarlo, quindi sono andato avanti, ma sono ancora curioso.]

EDIT: Come molti hanno sottolineato, il codice sopra ha vinto " t correre. Lo stavo eseguendo in una sessione IPython in cui la chiamata a A.clsMeth() faceva riferimento a una versione precedente di A ed eseguita. Tali sono i rischi dell'uso di un linguaggio interpretato, immagino. Ho finito per andare con qualcosa di simile:

outsideDict = {} 
def outsideDec(func): 
    outsideDict[func.__name__] = func 

class A(object): 
    @outsideDec 
    def someMethod(self): 
     print 'ID %s' % id(self) 

    def otherMethod(self): 
     print 'other' 

print outsideDict 
one, two = A(), A() 
outsideDict['someMethod'](one) 
outsideDict['someMethod'](two) 

Forse questo dovrebbe essere un'altra domanda, ma quando outsideDec viene investito, c'è un modo per dire quale classe è argomento è un membro del? O c'è un modo migliore di fare introspezioni come questa in Python? Riconosco che sto virando fuori rotta, quindi accetterò la risposta qui sotto e farò ulteriori ricerche. Grazie a tutti!

+0

Quello che ottengo è un errore quando si chiama 'A.clsMeth' perché' A' non è definito. Forse stai usando l'interprete e hai una vecchia definizione di 'A'? – jcollado

+0

Come si esegue questo esempio? Questo non può funzionare in quanto la sintassi non è corretta. 'A.clsMth()' non può essere posizionato come questo all'interno della definizione della classe. – gecco

+0

@gecco: certo che può; la sintassi va bene. Fallirà con un errore di runtime, come menzionato da jcollado, dato che l'assegnazione a 'A' non ha avuto luogo quando viene richiamato' A.clsMeth() ', ma è possibile farlo. –

risposta

4

La chiamata a A.clsMeth() nella definizione di A non verrà eseguito, come A non esiste in quel punto:

>>> class A(object): 
...  clsVar = 'a' 
...  @classmethod 
...  def clsMeth(cls): 
...   print 'changing clsVar' 
...   cls.clsVar = 'b' 
...  A.clsMeth() 
... 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 7, in A 
NameError: name 'A' is not defined 

Il codice può essere sembrato a lavorare se A era stato definito in precedenza (ad esempio, se lo stavi testando nel REPL), ma la chiamata a A.clsMeth sarebbe stata chiamata sulla vecchia classe, che sarebbe stata ombreggiata da quella nuova.

Tuttavia, possiamo sicuramente messo quella chiamata dopo la definizione e ottenere il risultato desiderato:

>>> class A(object): 
...  clsVar = 'a' 
...  @classmethod 
...  def clsMeth(cls): 
...   print 'changing clsVar' 
...   cls.clsVar = 'b' 
... 
>>> A.clsMeth() 
changing clsVar 
>>> A.clsVar 
'b' 

Naturalmente, come ha osservato fabianhrj, si può mettere nel costruttore pure, ma ha vinto' t essere chiamato fino a quando non si crea un'istanza.

0

È necessario inserire tutte le istruzioni in una funzione per farle funzionare. Raccomando che se vuoi eseguire qualcosa quando l'oggetto viene creato, inseriscilo nel costruttore.

class A: 
    def clsMeth(self): 
     print("Changing clsVar") 
     self.clsVar = 'b' 
    def __init__(self): 
     self.clsMeth() 
    clsVar = 'a' 

Ci siamo.

+0

Vuoi dire '__new__' o' __init__'? – kennytm

+0

Sì, lasciami passare il mio contesto a Python. –

+0

Ok risolto. Potresti confermare? –

Problemi correlati