Why isn't my class variable changed for all instances in Python?

Question:

I’m learning about classes and don’t understand this:

class MyClass:
    var = 1

one = MyClass()
two = MyClass()

print(one.var, two.var) # out: 1 1
one.var = 2

print(one.var, two.var) # out: 2 1

I thought that class variables are accessible by all instances, but why doesn’t it change for all of them?

Asked By: azertqwert

||

Answers:

It doesn’t change for all of them because doing this: one.var = 2, creates a new instance variable
with the same name as the class variable, but only for the instance one.
After that, one will first find its instance variable and return that, while two will only find the class variable and return that.

To change the class variable I suggest two options:

  1. create a class method to change the class variable (my preference)

  2. change it by using the class directly

class MyClass:
    var = 1

    @classmethod
    def change_var(cls, var): 
        cls.var = var


one = MyClass()
two = MyClass()

print(one.var, two.var) # out: 1 1

one.change_var(2)  # option 1
print(one.var, two.var) # out: 2 2

MyClass.var = 3     # option 2
print(one.var, two.var) # out: 3 3
Answered By: Stryder

Assignment to an attribute via an instance always creates/updates an instance variable, whether or not a class attribute of the same name exists. To update a class attribute, you must use a reference to the class.

>>> type(one).var = 2
>>> print(one.var, two.var)
2 2

In practice, type(one) might return the wrong class to update a particular class attribute, but also in practice, you don’t need to change class attributes when you only have an instance of the class available.

Answered By: chepner

one.var = 2 actually adds the new instance variable var by object but doesn’t change the class variable var and after adding the new instance variable var, one.var accesses the new instance variable var as shown below. *If there are the same name class and instance variables, the same name instance variable is prioritized while the same name class variable is ignored when accessed by object:

class MyClass:
    var = 1

one = MyClass()
two = MyClass()

print(one.var, two.var) 
one.var = 2 # Adds the new instance variable by object
                # ↓ Accesses the class variable by object 
print(one.var, two.var)
   #     ↑
   # Accesses the new instance variable by object

Output:

1 1
2 1

So, to change the class variable var, you need to use the class name MyClass as shown below:

class MyClass:
    var = 1

one = MyClass()
two = MyClass()

print(one.var, two.var) 
MyClass.var = 2 # Changes the class variable by the class name

print(one.var, two.var)

Output:

1 1
2 2

And basically, you should use class name to access class variables because you can always access class variables whether or not there are the same name instance variables. So, using class name is safer than using object to access class variables as shown below:

class MyClass:
    var = 1

one = MyClass()
two = MyClass()
      # Here       # Here
print(MyClass.var, MyClass.var)
MyClass.var = 2 # Changes the class variable by the class name
      # Here       # Here
print(MyClass.var, MyClass.var)

Output:

1 1
2 2

My answer for How to access "static" class variables in Python? explains more about accessing class variables.

Answered By: Kai – Kazuya Ito