2

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
  • 44,105
  • 12
  • 114
  • 143
user284094
  • 95
  • 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
  • 65,295
  • 17
  • 152
  • 131
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
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
  • 24,359
  • 19
  • 83
  • 121
Guillaume Lebourgeois
  • 3,796
  • 1
  • 20
  • 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
  • 112,946
  • 110
  • 377
  • 526
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,816
  • 3
  • 52
  • 60