Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free.

I'd like to store some information about a class as class (static) variables. However, I can't figure out how these things get initialized. Here is a basic, dumb example:

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'

Since the function got called (as the print statement worked), why didn't the class variable stay changed? Do I have to use a metaclass if I don't want to do it after the class definition completes?

[Specifically, I want clsMeth to be a decorator and have the class variable be a list of all the functions that were so decorated. I'm guessing this isn't the right way to go about accomplishing that, so I've moved on, but I'm still curious.]

EDIT: As numerous people have pointed out, the code above won't run. I was running it in an IPython session where the call to A.clsMeth() would refer to a previous version of A and run. Such are the risks of using an interpreted language, I guess. I ended up going with something like this:

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)

Perhaps this should be another question, but when outsideDec gets run, is there a way to tell what class it's argument is a member of? Or is there a better way of doing introspection like this in Python? I recognize I'm veering off course here so I'll accept the answer below and do more research. Thanks everyone!

share|improve this question
    
What I get is an error when calling A.clsMeth because A is undefined. Maybe are you using the interpreter and you have an old A definition? –  jcollado Dec 14 '11 at 18:45
    
How do you run this sample? This cannot work as the syntax is not correct. A.clsMth() cannot be placed like this inside the class definition. –  gecco Dec 14 '11 at 18:47
    
@gecco: Sure it can; the syntax is fine. It'll fail with a runtime error, as jcollado mentioned, since the assignment to A hasn't taken place when A.clsMeth() is invoked, but you can do it. –  Glenn Maynard Dec 14 '11 at 18:54

2 Answers 2

up vote 1 down vote accepted

The call to A.clsMeth() in the definition of A will not run, as A does not exist at that point:

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

The code may have seemed to work if A had been defined previously (eg, if you were testing it out in the REPL), but the call to A.clsMeth would have been called on the old class, which would be shadowed by the new one.

However, we can definitely put that call after the definition and get the result you want:

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

Of course, as fabianhrj noted, you can put it in the constructor as well, but it won't be called until you create an instance.

share|improve this answer

You need to put all statement in a function for them to work. I recommend that if you want to run something when the object is created just put it in the constructor.

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

There we are.

share|improve this answer
    
Do you mean __new__ or __init__? –  kennytm Dec 14 '11 at 18:43
    
Yes, let me switch my context to Python. –  Fabián Heredia Montiel Dec 14 '11 at 18:46
    
Ok fixed. Could you confirm? –  Fabián Heredia Montiel Dec 14 '11 at 18:50
1  
This called clsMeth every time an object is instanciated. Hardly useful. –  delnan Dec 14 '11 at 19:03
    
He put A.clsMeth() in the body of the class, that is what he meant. –  Fabián Heredia Montiel Dec 14 '11 at 19:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.