2011-12-14 39 views
5

Chciałbym zapisać pewne informacje o klasie jako zmiennych klasycznych (statycznych). Nie mogę jednak dowiedzieć się, jak te rzeczy zostały zainicjowane. Oto podstawowe, głupi przykład:Python Class Variable Initialization

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' 

Ponieważ funkcja nazywa mnie (jak instrukcja print pracował), dlaczego nie klasa zmienna pobyt zmieniło? Czy muszę używać metaclass, jeśli nie chcę tego zrobić po zakończeniu definicji klasy?

[W szczególności chcę, aby clsMeth była dekoratorem i zmienną klasy powinna być lista wszystkich funkcji, które zostały tak urządzone. Zgaduję, że to nie jest właściwa droga, aby to osiągnąć, więc ruszyłem dalej, ale nadal jestem ciekawy.]

EDYCJA: Jak wiele osób wskazało, powyższy kod wygrał ' t uruchom. Byłem uruchomiony w sesji IPython, gdzie wywołanie A.clsMeth() będzie odwoływać się do poprzedniej wersji A i uruchomić. Takie są zagrożenia związane z używaniem języka interpretowanego. I skończyło się z czymś takim:

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) 

Być może powinno to być kolejne pytanie, ale kiedy outsideDec dostaje uciekać, czy jest jakiś sposób, aby powiedzieć, co klasa to argument jest członkiem? Czy istnieje lepszy sposób wykonywania introspekcji w ten sposób w Pythonie? Rozumiem, że odchodzę tutaj, więc przyjmuję odpowiedź poniżej i zrobię więcej badań. Dziękuję wszystkim!

+0

Otrzymuję błąd podczas wywoływania 'A.clsMeth', ponieważ' A' jest niezdefiniowane. Może używasz tłumacza i masz starą definicję "A"? – jcollado

+0

Jak uruchomić tę próbkę? To nie działa, ponieważ składnia nie jest poprawna. 'A.clsMth()' nie może być umieszczone tak w definicji klasy. – gecco

+0

@gecco: Pewnie, że może; składnia jest w porządku. Nie powiedzie się z błędem runtime, jak wspomniał jcollado, ponieważ przydział do 'A' nie nastąpił, gdy' AclsMeth() 'jest wywołany, ale możesz to zrobić. –

Odpowiedz

4

Wezwanie do A.clsMeth() w definicji A nie będzie działać, jak A nie istnieje w tym momencie:

>>> 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 

Kod może wydawać się do pracy, jeśli A zostały zdefiniowane wcześniej (na przykład, jeśli testowałeś to w REPL), ale wywołanie A.clsMeth zostało wywołane na starej klasie, która mogłaby zostać zasłonięta przez nową.

Możemy jednak zdecydowanie postawić na to wezwanie po definicji i uzyskać wynik, który chcesz:

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

oczywiście, jak fabianhrj zauważyć, można umieścić go w konstruktorze, jak również, ale to won” Zostanie wywołana do momentu utworzenia instancji.

0

Musisz umieścić wszystkie instrukcje w funkcji, aby zadziałały. Polecam, jeśli chcesz uruchomić coś, gdy obiekt jest tworzony, po prostu umieść go w konstruktorze.

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

Tam jesteśmy.

+0

Masz na myśli '__new__' lub' __init__'? – kennytm

+0

Tak, pozwól mi zmienić kontekst na Python. –

+0

OK naprawione. Czy mógłbyś potwierdzić? –