2011-12-14 10 views
5

Me gustaría almacenar información sobre una clase como variables de clase (estáticas). Sin embargo, no puedo entender cómo se inicializan estas cosas. Aquí es un ejemplo tonto básica:Inicialización de variable de clase de 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' 

Dado que la función fue llamado (como la declaración de impresión trabajó), ¿por qué no cambia la clase variable de estancia? ¿Tengo que usar una metaclase si no quiero hacerlo después de que se complete la definición de la clase?

[Específicamente, quiero clsMeth para ser un decorador y la variable de clase sea una lista de todas las funciones que fueron decoradas. Supongo que esta no es la forma correcta de lograrlo, así que he seguido adelante, pero todavía tengo curiosidad.]

EDITAR: Como han señalado muchas personas, el código anterior ganó ' corre Lo estaba ejecutando en una sesión de IPython donde la llamada a A.clsMeth() se referiría a una versión anterior de A y se ejecuta. Tales son los riesgos de usar un lenguaje interpretado, supongo. Terminé yendo con algo como esto:

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) 

Tal vez esto debería haber otra pregunta, pero cuando se ejecute outsideDec, hay una manera de decir qué clase es argumento es un miembro de? ¿O hay una mejor manera de hacer una introspección como esta en Python? Reconozco que me estoy desviando del curso aquí, así que aceptaré la respuesta a continuación y haré más investigación. ¡Gracias a todos!

+0

Lo que obtengo es un error al llamar 'A.clsMeth' porque' A' no está definido. ¿Tal vez estás usando el intérprete y tienes una antigua definición 'A'? – jcollado

+0

¿Cómo se ejecuta esta muestra? Esto no puede funcionar ya que la sintaxis no es correcta. 'A.clsMth()' no se puede colocar así dentro de la definición de la clase. – gecco

+0

@gecco: Claro que sí; la sintaxis esta bien Fallará con un error de tiempo de ejecución, como mencionó jcollado, ya que la asignación a 'A' no se ha realizado cuando se invoca' A.clsMeth() ', pero puedes hacerlo. –

Respuesta

4

La llamada a A.clsMeth() en la definición de A no se ejecutará, como A no existe en ese 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 

El código puede haber parecido a trabajar si A se había definido previamente (por ejemplo, si lo estabas probando en el REPL), pero la llamada a A.clsMeth habría sido llamada en la clase anterior, que sería sombreada por la nueva.

Sin embargo, podemos poner definitivamente esa llamada después de la definición y obtener el resultado deseado:

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

Por supuesto, como fabianhrj señaló, se puede poner en el constructor así, pero ganó' Se llamará hasta que cree una instancia.

0

Debe poner todas las instrucciones en una función para que funcionen. Recomiendo que si desea ejecutar algo cuando se crea el objeto, simplemente colóquelo en el constructor.

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

Aquí estamos.

+0

¿Quiere decir '__new__' o' __init__'? – kennytm

+0

Sí, déjame cambiar mi contexto a Python. –

+0

Bien reparado. ¿Podrias confirmar? –

Cuestiones relacionadas