I am a beginner in Python, and using Lutz's book to understand classmethod, staticmethod and instancemethod. The objective of this code is to understand the difference among cls, self, and direct Class call (Spam1.numInstances) by counting number of instances created.
Here's an example derived from the book. I am unsure why parent class (Spam1) attribute (numInstances) doesn't increment when called through Sub1 and Other1, which are child classes.
Here's my code:
class Spam1:
    numInstances = 0
    def count(cls):
        cls.numInstances += 1
        print("In count -> number of instances: cls, Spam", cls.numInstances, Spam1.numInstances)
    def __init__(self):
        print("-----")
        print("In init, before -> number of instances: self, Spam",self.numInstances,Spam1.numInstances )
        self.count()
        print("In init, after -> number of instances: self, Spam",self.numInstances,Spam1.numInstances )
        print("-----")
    count=classmethod(count)
class Sub1(Spam1):
    numInstances = 0
class Other1(Spam1):
    pass
a=Spam1() #Output after increment: 1,1,1 (self, cls, Spam1)
b=Spam1() #Output after increment: 2,2,2 (self, cls, Spam1)
c=Spam1() #Output after increment: 3,3,3 (self, cls, Spam1)
d=Sub1()  #Output after increment: 1,1,3 (self, cls, Spam1)
e=Sub1()  #Output after increment: 2,2,3 (self, cls, Spam1)
f=Other1() #Output after increment: 4,4,3 (self, cls, Spam1)
I have spent one day trying to debug this code, but I cannot understand how cls.numInstances works because PyCharm would show "no reference" for cls.numInstances in debug mode. Being frustrated, I read a few SO threads: What does cls() function do inside a class method?, What is the 'cls' variable used for in Python classes?, and Python - self, no self and cls, but I cannot understand what's going on. 
Specifically, here are my questions:
a) why is it that Spam1.numInstances doesn't increase when d, e, and f are created? 
Here's my attempt to answer this question:
a.i) It is my understanding that cls is used to access class attributes. For d and e, self.numInstances is used to access instance attribute, which is zero because Sub1 zeroes the value of inherited attribute numInstances from Spam1. cls accesses class attribute of Sub1, which is also the same as attribute of Sub1 class. Hence, self and cls values we see in the output are of Sub1 instance and class respectively. Is my understanding correct?
a.ii) f inherits numInstances from Spam1. Hence, self.numInstances and cls.numInstances of f take the value from Spam1. Their value is incremented but not of Spam1 because cls refers to Other1 and because self refers to f, which is the object of Other1. Hence, Spam1's numInstances is never touched. 
b) Is my understanding about the differences among self.numInstances, cls.numInstances, and Spam1.numInstances correct? If not, can someone please explain it?
I believe that my question is very basic. I hope someone will help me out. I am lost.
 
     
    