From Dive into Python:
Class attributes are available both through direct reference to the
class and through any instance of the class.
Class attributes can be used as class-level constants, but they are
not really constants. You can also change them.
So I type this into IDLE:
IDLE 2.6.5
>>> class c:
counter=0
>>> c
<class __main__.c at 0xb64cb1dc>
>>> v=c()
>>> v.__class__
<class __main__.c at 0xb64cb1dc>
>>> v.counter += 1
>>> v.counter
1
>>> c.counter
0
>>>
So what am I doing wrong? Why is the class variable not maintaining its value both through direct reference to the class and through any instance of the class.
Because ints are immutable in python
v.counter += 1
rebinds v.counter
to a new int object. The rebinding creates an instance attribute that masks the class attribute
You can see this happening if you look at the id()
of v.counter
>>> id(v.counter)
149265780
>>> v.counter+=1
>>> id(v.counter)
149265768
Here you can see that v
now has a new attribute in its __dict__
>>> v=c()
>>> v.__dict__
{}
>>> v.counter+=1
>>> v.__dict__
{'counter': 1}
Contrast the case where counter
is mutable, eg a list
>>> class c:
... counter=[]
...
>>> v=c()
>>> v.counter+=[1]
>>> c.counter
[1]
>>>
Before:
c.counter = 0
v.counter -> c.counter
During:
c.counter = 0
v.counter = c.counter + 1
After:
c.counter = 0
v.counter = 1
Note that you can still get at the class value:
v.__class__.__dict__['counter']
will allow you to read or set to your class, even if you have obscured the symbol by adding a symbol to your instance's __dict__.
Your are confused between declaration and instantiation.
C is the name of a class you declared.
v is an object, instantiated from c.