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?
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:
-
create a class method to change the class variable (my preference)
-
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
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.
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.
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?
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:
-
create a class method to change the class variable (my preference)
-
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
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.
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.