Class variables versus Instance variables

According to the explanations of https://www.codecademy.com/courses/learn-python-3/lessons/data-types/exercises/class-variables a class variable is a variable that’s the same for every instance of the class.
Here is a piece of code

class SomeClass:
    def __init__(self):
        self.foo_num = 1
        self.foo_list = []

    bar_num = 2
    bar_list = []
    
sc1 = SomeClass()
sc1.foo_list.append(1)
sc1.bar_list.append(2)
sc1.bar_num = 3

sc2 = SomeClass()
sc2.foo_list.append(10)
sc2.bar_list.append(20)
sc2.bar_num = 30

print(sc1.foo_list)
print(sc1.bar_list)
print(sc1.bar_num)

print(sc2.foo_list)
print(sc2.bar_list)
print(sc2.bar_num)

The output of the code is
[1]
[2, 20]
3
[10]
[2, 20]
30

It looks like when I am changing the Class variable list (bar_list) this is reflected in both object sc1 and sc2, while bar_num is behaving like an instance variable. Why is this happening?

When we assign a new value to a class variable, it becomes an attribute of the object it is assigned on. However, when we append to a list on the class, it is not an assignment. The list still belongs to the class.

It’s analogous to variables and lists in the global namespace surrounding a function:

x = 5
lst = ['a','b','c']
def my_funct(x, lst):
    x += 10   # this is a new variable, living only in the function namespace
    lst.append('x')
    
my_funct(x, lst)
print(x)
print(lst)

# Output:
5     #  x defined outside of function unchanged; x defined inside the function invisible here
['a', 'b', 'c', 'x']        # list has been modified

To make use of class variables, they can be changed as each new class object is instantiated (Here’s an example.), or you can have setters & getters. Somewhere outside of the class definition, you could also do SomeClass.bar_num += 1, but I think that would be considered very bad practice.

Hi Roy,
Thanks for your answer.
Does this has to do with the fact that a list is mutable and the int is immutable, or is it something different?

It has to do with reassignment. Appending to the list did not change its owner. Changing the value of a class variable creates a new object (attribute) on the instance that changed it. The class variable still exists and is unchanged, but is no longer accessible to the instance (except by Class.name).

Thanks Roy
Now I understand :smiley: