2011-01-26

Python class attributes versus instance attributes

Today I finally found out the difference between class and instance attributes in Python. In C++, this is done by putting the static modifier in front of the declaration. Consider the following code:

#!/usr/bin/env python

class B:
    b = 2

class C:
    a = B()

    def __init__(self):
        self.a.b = 1

c = C()
c.a.b = 3
b = C()

print c.a.b, b.a.b

Here, a is a class attribute of class C. That is, there exists only one such attribute for all objects of kind C. So the output of the print statement will be "1 1". This is the same as a static attribute in C++. But often I want an instance attribute. The correct way to do this would have been:

#!/usr/bin/env python

class B:
    b = 2

class C:
    def __init__(self):
        self.a = B()
        self.a.b = 1

c = C()
c.a.b = 3
b = C()

print c.a.b, b.a.b

Now the output is "3 1", just as expected. I guess this all somehow makes sense in the Python world, but I tripped over this, and worst of all: Sometimes you don't even notice. If the class attribute is a simple type, like int, the first solution would have worked. However, I have not yet understood why that is the case. One more Python semantic that eluded me so far.

2 comments:

  1. A common trick is to convert the class attributes to instance attributes on instantiation (like django/appengine do for the models). It's a little tricky though, as you usually write a custom metaclass that performs the instantiation on __init__. It's a few lines of code, but you should really know what you're doing :-)

    ReplyDelete
  2. Can you give an example?

    Because I personally like to list my attributes at the top of the class, to get an overview of them when browsing the code. So it would be nice to have the attributes outside of __init__.

    ReplyDelete