pythonpython-3.xclassvariables

Working with class variable in Python 3.x


I have one small question regarding Python classes and variables.

Why 'self' keyword 'spoils' the work of counter variable in the first example while in 2nd example (which is pretty similar in terms of mechanism to the first one) 'self' keyword does not do anything 'wrong' in terms of the outcome:

# Counter does not work properly (incrementation) if 'self' keyword is provided before the variable named 'counter'.
# Instead of 'self' keyword we shall use class name, to make this work 'ExampleOne.counter += 1'.
class ExampleOne:
    counter = 0

    def __init__(self, name, surname):
        self.name = name
        self.surname = surname
        self.counter += 1


# It works, meaning list is being updated. Even if 'self' keyword is provided before variable named 'list'.
class ExampleTwo:
    list = []

    def __init__(self, name, surname):
        self.name = name
        self.surname = surname
        self.list.append([self.name, self.surname])

Solution

  • self.counter, when looking up a value, will check the class after the instance; but when assigning a value, will just assign to the instance (because it tries the instance first and will succeed - there's nothing to prevent it from working).

    self.counter += 1 is equivalent to self.counter = self.counter + 1; the newly computed value, based on the class attribute, is assigned as an instance attribute.

    self.list.append(...) calls a method on the looked-up list object; that object's identity never changes and there is no assignment. So each access to self.list finds the class attribute, since there are never any instance attributes to be found first.

    For more technical details, you can see e.g. How python attribute lookup process works? .

    You might wonder why the lookup is allowed to find class attributes via the instance in the first place. The reason is that it is sometimes useful for polymorphism; depending on the subtype of the instance, a class attribute could be found in a different class.