Question: I am attempting to experiment with classes so I can better understand what they do. I wanted to build a counter which records the number of instances of a class (MyClass): class ObjectCounter: # I want this to count the number of objects in each class myclass_obj_count = 0 class MyClass(ObjectCounter): def __init__(self): super().myclass_obj_count += 1 # AttributeError: 'super' object has no attribute 'myclass_obj_count' m1 = MyClass() m2 = MyClass() m3 = MyClass() print(ObjectCounter.myclass_obj_count)  Since that didn't work, I looked online for someone trying to do the same thing. Here is some code I found online. This works as expected, and I feel like I have a basic understanding of how this works. This is a better solution to the task I was attempting, but I'm not satisfied because I want to know how super() works. class geeks: counter = 0 def __init__(self): geeks.counter += 1 g1 = geeks() g2 = geeks() g3 = geeks() print(geeks.counter) # this gives an expected result  Therefore, I tried this instead: class ObjectCounter: # I want this to count the number of objects in each class myclass_obj_count = 0 def add_myclass(self): self.myclass_obj_count += 1 class MyClass(ObjectCounter): def __init__(self): super().add_myclass() my_class_1 = MyClass() my_class_2 = MyClass() my_class_3 = MyClass() print(ObjectCounter.myclass_obj_count) # expected output: 3  Instead of getting the expected output of 3, I got an output of 0. Why is this happening?

Answer: First, be aware of the += operator; it's implementation is quite subtle: a += b  becomes a = a.__iadd__(b)  This perhaps strange definition allows python to support it even for immutable types (like strings). Note what happens when used for a class variable that is referred to by the alias self class ObjectCounter: # I want this to count the number of objects in each class myclass_obj_count = 0 def add_myclass(self): self.myclass_obj_count += 1 # effectively becomes: # self.myclass_obj_count = self.myclass_obj_count.__iadd__(1)  This will introduce an instance variable of the same name, shadowing the class variable. You don't even need the subclass to test this: >>> x = ObjectCounter() >>> x.add_myclass() >>> x.add_myclass() >>> x.add_myclass() >>> x.myclass_obj_count 3 >>> ObjectCounter.myclass_obj_count 0  Referring to the class variable directly instead of using self fixes this  def add_myclass(self): ObjectCounter.myclass_obj_count += 1  I'm hesitant to give definite answers of what happens under the hood when class variables, super() and assignments are used, other than it just doesn't work. Perhaps because it would be quite ambiguous of whether or not we are defining class variables or new instance variables. super() won't let you assign to either; class ObjectCounter: myclass_obj_count = 0 def __init__(self): self.x = 'test' class MyClass(ObjectCounter): def __init__(self): super().__init__() print(super().myclass_obj_count) # reading works just fine print(type(super())) # this isn't actually exactly the same as "ObjectCounter" super().myclass_obj_count = 123 # no good super().x = 'foo' # also no good.  All in all, for any assignment to class variables you can use the class name itself.