Why did my output change when I called the class attribute from an instance instead of the class?

Question:

(I’m fairly new to programming, so understand that my quary might not make sense. I’ve tried my best to explain it but if you are still confused, you can ask me to reclarify.)

I undertsand the that we can call the class attribute number_of_people and increment by one so that when we create a new instance (in this context, a person), the number of people increases by one:

class Person:

     # Class attribute
     number_of_people = 0

     # Constructor
     def __init__(self, name):
        self.name = name
        # Everytime we call the constructor, we increment the number of people.
        Person.number_of_people += 1

# Driver code
p1 = Person("Jack")
print(Person.number_of_people)
# output gives 1

However, I’m having trouble with understanding the output of the code when we change the we choose to increment p1.number_of_people instead of Person.numer_of_people:

class Person:

     # Class attribute
     number_of_people = 0

     # Constructor
     def __init__(self, name):
        self.name = name
        # Everytime we call the constructor, we increment the number of people.
        p1.number_of_people += 1

# Driver code
p1 = Person("Jack")
print(p1.number_of_people)
# output gives 0 (I expected the output to be 1)

I thought that since class attributes can be accessed by both the class and instances, my change wouldn’t make a difference. I suspect it has to do with p1 being mentioned in the class before it’s mentioned in the driver code, but I’m not sure where to go from there.

Asked By: Micheal Keens

||

Answers:

I suspect the demonstration you were trying to do for yourself is to examine the difference between using the class attribute as a class attribute, vs as an instance attribute. Consider this difference:

class Person:
    population = 0

    def __init__(self,name):
        self.name = name
        Person.population += 1

p1 = Person("Jack")
p2 = Person("Tom")
p3 = Person("Bill")
print(p1.population)
print(p2.population)
print(p3.population)

Output:

3
3
3

Compared to:

class Person:
    population = 0

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

p1 = Person("Jack")
p2 = Person("Tom")
p3 = Person("Bill")
print(p1.population)
print(p2.population)
print(p3.population)

Output:

1
1
1

In the second example, the instance starts out using the class attribute, but as soon we change it, it creates an instance attribute that has a separate life.

Answered By: Tim Roberts