2010-03-30 10 views
8

Mi scuso se ho la terminologia sbagliata qui-non riesco a pensare a quale sarebbe il nome di questo particolare idioma.Creare istanze statiche di una classe all'interno di detta classe in Python

Ho cercato di creare una classe Python 3 che dichiari staticamente le istanze di se stesso dentro di sé, un po 'come se un enum potesse funzionare. Ecco una versione semplificata del codice che ho scritto:

class Test: 
    A = Test("A") 
    B = Test("B") 

    def __init__(self, value): 
     self.value = value 

    def __str__(self): 
     return "Test: " + self.value 

print(str(Test.A)) 
print(str(Test.B)) 

Scrivendo questo, ho ricevuto un'eccezione sulla linea 2 (A = Test("A")). Presumo che la riga 3 sarebbe anche un errore se fosse arrivato così lontano. L'utilizzo di __class__ anziché Test restituisce lo stesso errore.

File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in Test 
NameError: name 'Test' is not defined 

C'è un modo per fare riferimento alla classe corrente in un contesto statico in Python? Potrei dichiarare queste variabili particolari al di fuori della classe o in una classe separata, ma, per motivi di chiarezza, preferirei non se posso aiutarla.

Per dimostrare meglio quello che sto cercando di fare, ecco lo stesso esempio in Java:

public class Test { 
    private static final Test A = new Test("A"); 
    private static final Test B = new Test("B"); 

    private final String value; 

    public Test(String value) { 
     this.value = value; 
    } 

    public String toString() { 
     return "Test: " + value; 
    } 

    public static void main(String[] args) { 
     System.out.println(A); 
     System.out.println(B); 
    } 
} 

Questo funziona come ci si aspetterebbe: la stampa:

Test: A 
Test: B 

Come posso fare la stessa cosa in Python?

risposta

9

Dopo aver definito la classe, basta aggiungere queste due linee:

Test.A = Test("A") 
Test.B = Test("B") 

Una classe in Python è un oggetto come un altro e si può aggiungere nuove variabili in qualsiasi momento. Non puoi farlo all'interno della classe poiché non è definito in quel momento (verrà aggiunto alla tabella dei simboli solo dopo che l'intero codice per la classe è stato analizzato correttamente).

+0

Naturalmente-non credono non ho visto questo. Grazie mille per il tuo aiuto. –

2

In Python, un blocco class non è solo una dichiarazione; viene eseguito in fase di esecuzione per creare la classe. Ogni def all'interno della classe crea una funzione e associa il nome nello spazio dei nomi della classe. Per questo motivo, non puoi semplicemente fare A = MyClass() direttamente all'interno del blocco di classe, perché MyClass() non è completamente definito fino alla chiusura del blocco di classe. Ecco come fare:

class Test: 
    def __init__(self, value): 
     self.value = value 

    def __str__(self): 
     return "Test: " + self.value 

Test.A = Test("A") 
Test.B = Test("B") 
2

Mentre la risposta del Aaron è il modo preferito è anche possibile utilizzare metaclassi:

>>> class TestMeta(type): 
... def __init__(cls, name, bases, dct): 
... cls.A = cls() 
... cls.B = cls() 
... 
>>> class Test: 
... __metaclass__ = TestMeta 
... 
>>> Test 
<class __main__.Test at 0x7f70f8799770> 
>>> Test.A 
<__main__.Test object at 0x7f70f86f2e10> 
>>> Test.B 
<__main__.Test object at 0x7f70f86f2e90> 
>>> 
+0

Piuttosto interessante. I metaclassi sono qualcosa con cui non ho mai giocato prima. Dovrò provarli prima o poi. –

Problemi correlati