0

I am baffled by the Python behaviour below. Why the attributes of second and third instances (b, c), i, are the class attribute i but a behaves differently?

In [47]: class Foo:
    ...:     i=0
    ...:

In [48]: a = Foo()

In [49]: a.i = 1

In [50]: a.i
Out[50]: 1

In [51]: Foo.i
Out[51]: 0

In [52]: b = Foo()

In [53]: b.i
Out[53]: 0

In [54]: Foo.i is b.i
Out[54]: True

In [55]: Foo.i is a.i
Out[55]: False

In [56]: c = Foo()

In [57]: Foo.i is c.i
Out[57]: True
1
  • 1
    Careful with interpreting the results of int is int... Python caches small integers. Perhaps it is better to use a dummy class for such demonstrations, although, in this case I don't think it will affect your demonstration. Commented Dec 14, 2016 at 0:01

2 Answers 2

6

Here's what happens. When you do:

a.i = 1

You create an instance variable with a name that shadows the class attribute. The class attribute is still there, though:

>>> class Foo:
...     i = 0
...     
>>> a = Foo()
>>> Foo.i
0
>>> a.i = 69
>>> a.i
69
>>> a.__class__.i
0
>>> del a.i  # deletes the instance attribute, resolving lookup on class
>>> a.i
0

To see what lives in the instance's namespace, check out the instance dict:

>>> a = Foo()
>>> a.__dict__
{}
>>> a.i = 1
>>> a.__dict__
{'i': 1}
Sign up to request clarification or add additional context in comments.

Comments

0

a.i = 1 does NOT change Foo.i as you intended. It rather assigns an instance member of a. It is very clear if you see a.__dict__ and b.__dict__.

In [11]: a.__dict__
Out[11]: {'i': 1}

In [13]: b.__dict__
Out[13]: {}

If you want to really change class member variable, you should use Foo.i = 1. That will impact all Foo instances. Again, it is very clear on Foo.__dict__.

In [17]: Foo.__dict__
Out[17]: 
mappingproxy({'__dict__': <attribute '__dict__' of 'Foo' objects>,
              '__doc__': None,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'Foo' objects>,
              'i': 0})

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.