In what cases should i use self keyword?

I have a simple question but which confuses me for a long time. This is the example code:

class test():
    def func(self):
        
        lst = []
        self.num = 0
        
        def method(tmp):
            lst.append(tmp)
            self.num += 1
        
        method(1)

The question is, why do I need to add self before num, but for lst, i dont need to do that?

self.num is making num global inside func?


Solution 1:

self is a reference to the instance of the class. So, self.num is referencing the property num on the instance, while lst is a local variable to that method.

class test:
    def func(self):
        self.lst = [0, 1, 2, 3]
        lst = [5, 6, 7, 8]
        print(self.lst) # [0, 1, 2, 3]
        print(lst) # [5, 6, 7, 8]

    def test(self):
        print(self.lst) # [0, 1, 2, 3]
        print(lst) # Error

i = test()
i.func()
i.test() # Error, see above

Solution 2:

Without the self the code doesn't work because Immutable vs Mutable types, But this code will:

class test():
    def func(self):
        
        lst = []
        num = 0
        
        def method(tmp):
            nonlocal num
            lst.append(tmp)
            num += 1
        
        method(1)

This is because a list is mutable, and so it will not make a copy when editing the value of lst. While when the value of num is changed, it will make a new variable (local num). see docs nonlocal

Note you cannot access num outside of func. So this will not work(while it previously would)

t = test()
t.func()
print(t.num) # doesn't exist!

Solution 3:

func is member function of the class. method is just a standalone function, unrelated to the class. In order to call func, you have to say:

obj.func()

Python handles that by automatically passing the obj as the first parameter, which we have traditionally called self. But to call method, you just say:

method(1)

There is no object, so there is no automatic creating of a first parameter. When you refer to self and num inside of method, you're referring to the local variables in the outer function, which it inherits.