I'm practicing the following code:
class MITPerson(Person): # a subclass of class Person
nextIdNum = 0 # identification number
def __init__(self, name):
Person.__init__(self, name)
self.idNum = MITPerson.nextIdNum
MITPerson.nextIdNum += 1
def getIdNum(self):
return self.idNum
For a reference, here is the superclass:
class Person(object): # superclass
def __init__(self, name):
"""Create a person"""
self.name = name
I thought that I've already known the answer of this question since I try the following instances:
p1 = MITPerson('Mark Guttag')
p2 = MITPerson('Billy Bob Beaver')
p3 = MITPerson('Billy Bob Beaver')
Not surprisingly, when I type these into console:
In[12]: p1.getIdNum()
Out[12]: 0
In[13]: p3.getIdNum()
Out[13]: 2
I've read this post and checked all the excellent answers here: Static class variables in Python
I saw that nextIdNum is assigned to 0 when the first instance p1 is created. What I feel weird is that why not p2 and p3 also bind nextIdNum to 0 again? In my imagination, the class variable should be reassigned to 0 once a class MITPerson is created without calling the method.
Did I miss something?
By the way, I've also go through the tutorial here: https://docs.python.org/3.6/tutorial/classes.html#class-objects
However, I'm afraid it does not give out the answer :(
I saw that nextIdNum is assigned to 0 when the first instance p1 is created.
This is wrong. nextIdNum is assigned to 0 when the class is defined.
A class statement is a kind of wrapper around a single call to type. The statements in the body are evaluated, then added to a dict that is passed to type.
Yours is roughly equivalent to
def _init_(self, name):
Person.__init__(self, name)
self.idNum = MITPerson.nextIdNum
MITPerson.nextIDNum += 1
def _getIdNum(self):
return self.idNum
MITPerson = type(
'MITPerson',
(Person,),
{
'__init__': _init,
'getIdNum': _getIdNum,
'nextIdNum': 0
}
)
del _init, _getIdNum
You can see that nextIdNum gets initialized to 0 immediately, before any instances of MITPerson are created, just like __init__ and getIdNum.
When you create an instance, the following steps occur:
MITPerson('Mark Guttag') resolves to type.__call__(MITPerson, 'Mark Guttag').__call__ invokes MITPerson.__new__('Mark Guttag'), which creates a new instance of MITPerson.MITPerson.__init__, at which point the current value of MITPerson.nextIdNum is used before incrementing the class variable.__init__ returns, __new__ returns that value, at which point it is assigned to p1.Notice none of the code in the body of the class statement is executed again, although the function __init__ defined there is.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With