1

Based on the explanation on Shared Variables in Python Class here , I expected the following code to give output as :

123 123
200 200
300 300

But it is

123 123
200 123
200 300

Code:

class A:
    abc = 123
    def __init__(self, a,b,c):
        self._a = a
        self._b = b
        self._c = c


if __name__ == '__main__':
    a = A(2, 4, 6)
    b = A(3, 9, 27)

    print a.abc , b.abc
    a.abc = 200
    print a.abc , b.abc
    A.abc = 300
    print a.abc , b.abc

Can somebody please help understand this ? My impression is that shared variables are same as static variables in C++ classes. Any insights to bust that myth, if it is so, would be helpful too.

Community
  • 1
  • 1
ViFI
  • 971
  • 1
  • 11
  • 27
  • They are different objects, changing one should not affect another. – Ahsanul Haque Aug 30 '16 at 18:08
  • `a.abc = 200`, you create a new instance variable called `abc` for object a. – ospahiu Aug 30 '16 at 18:10
  • @AhsanulHaque : but "abc" should be shared object per say. Isn't it ? – ViFI Aug 30 '16 at 18:10
  • 1
    when you do `a.abc = ...` you create an instance variable that is completely seperate from the class variable `A.abc`, so changing `A.abc` will reflect that change in all other instances where as `a.abc` will only change that one instance. – Tadhg McDonald-Jensen Aug 30 '16 at 18:10
  • Change `a.abc = 200` to `A.abc = 200' – ospahiu Aug 30 '16 at 18:11
  • @TadhgMcDonald-Jensen : And python allows creating a instance variable even though it clashes with the name of shared variable ? Any particular reason for that ? – ViFI Aug 30 '16 at 18:12
  • lets say that a class may or may not define a particular attribute, specifying the default in the class definition like `x= None ; y = None` etc. is less execution work and cleaner then doing in the initialization like; `self.x = None ; self.y = None` Also this is exactly what happens when you define a method in a class that also has a viable method on the metaclass like `__repr__` so there would need to be extra special rules to disallow this behaviour in certain cases which is very un-pythonesque. – Tadhg McDonald-Jensen Aug 30 '16 at 18:16

4 Answers4

4

You are creating a new instance variable -> a.abc and setting it to 200. Access the shared static variable instead.

a = A(2, 4, 6)
b = A(3, 9, 27)
print a.abc , b.abc
A.abc = 200  # Set static class variable, instead of creating new instance member
print a.abc , b.abc
A.abc = 300
print a.abc , b.abc

I recommend reading the very informative Python official docs on [9] Classes.

ospahiu
  • 3,465
  • 2
  • 13
  • 24
  • 3
    I thought the question was *why* the output was what it was, not how to change the code to produce the expected output. – Scott Hunter Aug 30 '16 at 18:15
  • 1
    It gives unexpected output because of the instance variable being created. I can go into an explanation of python's run-time dispatching, and how classes are objects. Which is why you can add members to at run-time. `self` and `a` are just instances, and behave the same. Initializers behave, and are implemented far differently in python then they are in static languages like c/c++. I kept the answer brief. – ospahiu Aug 30 '16 at 18:19
4

Initially, the class A has an abc defined to be 123, which each of a and b use since neither has an abc of their own.

Then you execute a.abc = 200, which creates an abc for a; b still uses the one from A.

Then you execute A.abc = 300, which updates the abc for A, which b still looks to, so it see the new value. But a has its own abc, and so doesn't care.

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
0

@Scott Hunter's answer explains the behavior of code in question best but I would like to add C++ perspective to it here. Unfortunately it couldn't be added as comment in that answer as it is too long.

As in C++, to access static members name needs to be qualified by class name (e.g. A::abc or A::func_static() ) , in Python also you have to access the shared variable outside the class using Class name as qualifier.

Within the class, C++ allows to use the static variable name as like other member variables (i.e. without any qualifier) and same is true with Python as well, as shared variables can be accessed using self such as self.abc here.

Only thing which is different here is Python allows you to create an instance variable with the same name as shared variable for that instance only.

Community
  • 1
  • 1
ViFI
  • 971
  • 1
  • 11
  • 27
-1

Your expected output would mean that you can't change the attribute of an object without changing the attribute of every instance of the objects class. That would obviously break the core of the object orientation idea. I think you can overwrite "shared" variables because this gives just more possibilities.

timakro
  • 1,739
  • 1
  • 15
  • 31