1

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.

vaultah
  • 40,483
  • 12
  • 109
  • 137
user284094
  • 85
  • 4
  • Since c.counter is still 0, you obviously did not change its value. You did howver change the value of the counter attribute of the v instance. – Philippe F Aug 02 '10 at 15:27
  • You are looking for "static class variables", I think. Possibly a duplicate of http://stackoverflow.com/questions/68645/static-class-variables-in-python – Andrew Jaffe Aug 02 '10 at 15:31

4 Answers4

8

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]
>>> 
mikej
  • 63,686
  • 16
  • 149
  • 130
John La Rooy
  • 281,034
  • 50
  • 354
  • 495
0

Your are confused between declaration and instantiation.

C is the name of a class you declared.

v is an object, instantiated from c.

Oddthinking
  • 22,854
  • 19
  • 79
  • 119
Guillaume Lebourgeois
  • 3,698
  • 1
  • 18
  • 23
  • That's not the confusion here. If you set a variable on a class, you can read it just fine in exactly the manner above: instance.classvariable. – Seamus Campbell Aug 02 '10 at 15:31
0

Before:

c.counter = 0
v.counter -> c.counter

During:

c.counter = 0
v.counter = c.counter + 1

After:

c.counter = 0
v.counter = 1
Matt Joiner
  • 106,562
  • 103
  • 351
  • 513
0

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

Seamus Campbell
  • 17,568
  • 3
  • 50
  • 60