Static variable vs Class variable
Bruno Desthuilliers
bdesth.quelquechose at free.quelquepart.fr
Sat Oct 6 02:28:12 EDT 2007
minkoo.seo at gmail.com a écrit :
> Hi.
>
> I've got a question on the differences and how to define static and
> class variables.
What's a "static" variable ? A variable that doesn't move ?-)
> Hence, my understanding is that static variables must be bound to the
> class defining the variables
You mean "class attributes". Thinking in terms of another language won't
help understanding Python's objec model.
> and shared by children of parent class
> where the variable is defined. But, please have a look at this code in
> which a guy told me that the variable a is static:
Then don't listen what this guy says.
>>>>class Foo:
>
> a = 1
> @classmethod
> def increment(cls):
> cls.a += 1
> print cls.a
>
> Here, I am defining variable a which, I believe is class variable,
a class attribute
> i.e., variable that is not bound to Foo itself.
Yes it is. It's an attribute of the class object Foo.
> Rather, a is bound to
> the class which is accessing the variable.
False.
>>> dir(Foo)
['__doc__', '__module__', 'a', 'increment']
>>> Foo.__dict__
{'a': 1, '__module__': '__main__', '__doc__': None, 'increment':
<classmethod object at 0x402d141c>}
> The code that corroborates
> this idea is as follows:
>
>>>>class Child1(Foo):
> pass
>
>>>>Child1.increment()
> 4
???
>
>>>>class Child2(Foo):
> pass
>
>>>>Child2.increment()
> 4
I don't have the same result here. But anyway: the increment method is
rebinding 'a', so the first time it's called on a child class, it
creates an attribute 'a' for this class. Just change your code this way
and you'll see what happens:
def increment(cls):
print dir(cls)
cls.a += 1
print dir(cls)
FWIW, if you don't get this, then you may encounter another common gotcha:
class Truc:
a = 1
def gotcha(self):
self.a += 1
print self.a
print Truc.a
t = Truc()
print t.a
t.gotcha()
print Truc.a
t2 = Truc()
print t2.a
t2.gotcha()
print Truc.a
t.gotcha()
print t.a
print t2.a
print Truc.a
Enjoy !-)
Now back to your snippet : if you don't want this behaviour, wrap 'a'
into a mutable container:
class Foo:
a = [1]
@classmethod
def increment(cls):
cls.a[0] += 1
print cls.a[0]
class Child(Foo):
pass
And if you want to hide that, use properties (warning: you need nex
style classes here):
class Foo(object):
_a = [1]
@classmethod
def increment(cls):
cls._a[0] += 1
print cls._a[0]
@apply
def a():
def fget(self):
return type(self)._a[0]
def fset(self, val):
type(self)._a[0] = val
return property(**locals())
class Child(Foo):
pass
> This means that Child1 and Child2 does not share variable a which
> means that variable a is class variable rather than static variable.
Nope. This only means that you don't understand the (somewhat peculiar)
semantics of bindings, immutable objects and attribute lookup rules in
Python.
> Could you please comment on this? Is a static or class variable?
It's a class attribute.
> What's the most recent way of defining 'class' and 'static' variables?
No 'static variable' in Python. And what you call a 'class variable' is
nothing else than an ordinary of the class object
More information about the Python-list
mailing list