3

Here's a bit of a newbie Python question about instance variables.

Consider the following Python 2.7 class definition:

class Foo(object):
    a = 1

    def __init__(self):
            self.b = 2

    def __repr__(self):
            return "%s" % self.__dict__

Now, when I create an instance of Foo, Foo.__dict__ contains b, but not a.

>>> x=Foo()
>>> x
{'b': 2}
>>> dir(x)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', 
 '__getattribute__', '__hash__', '__init__', '__module__', '__new__', 
 '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
 '__str__', '__subclasshook__', '__weakref__', 'a', 'b']
>>> x.__dict__
{'b': 2}

And here I thought I had a pretty good grasp on the Way of the Python.

What's the difference between x.a and x.b? As far as I can tell they're both instance variables.

Edit: OK, re-reading the Python docs I see that Foo.a is a class attribute rather than an instance variable. Hm... I guess the confusion comes from the fact that I can assign a new value to x.a and the new value only affects the x instance -- I suppose I'm now aliasing a member variable over the top of the Foo.a attribute:

>>> y=Foo()
>>> y.a = 2
>>> y
{'a': 2, 'b': 2}
>>> x
{'b': 2}
>>> x.a
1
>>> z=Foo()
>>> z
{'b': 2}
>>> z.a
1
>>> Foo.a
1
>>> x.a
1
>>> y.a
2

So, now I overwrite the previous value of Foo.a, and it affects all instances of Foo that haven't aliased Foo.a:

>>> Foo.a=999
>>> x.a
999
>>> y.a
2
2
  • Note also that it's not good practice to rely on __dict__ too much: clases using __slots__ and extension classes (from C or Cython) don't put everything in there either. Most uses can be replaced by some combination of getattr, setattr, hasattr, and dir. Commented May 12, 2012 at 19:36
  • @Dougal: Thanks for that advice -- I saw that on another answer here on StackOverflow, but it's good reinforcement. Commented May 12, 2012 at 20:01

3 Answers 3

8

Your a isn't an instance variable. You defined it as part of the class.

>>> class Foo(object):
...    a = 1
...
>>> Foo.a
1

If you want an instance variable you should put it inside the __init__ method, because this method is called when your object is created.

Sign up to request clarification or add additional context in comments.

Comments

4

a is not an instance attribute, it's a class attribute.

3 Comments

Yes, but if I assign a new value to x.a it affects only the x instance. If it's a class attribute, why doesn't changing the value of x.a affect all instances of Foo?
Because you assigned it on the instance.
Yes, I see that now. I missed that on my initial read of the docs. Thanks for the assist!
0

May this help you further?

>>> class X(object):

    def __getattribute__(self, name):
        print name
        return object.__getattribute__(self, name)


>>> l = dir(X())
__dict__
__members__
__methods__
__class__
>>> l
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.