I would expect the following code to print 012345 but it prints 012012. Why? I would expect the calls to incr to be accessing the same variables since they are inherited fro
Both class b
and class c
inherit from class a
separately, and var
is set to 0 each time.
One way to have class c
to get the same value of var
in class a
as class b
does, class c
can inherit from class b
like so:
class a(object):
var = 0
@classmethod
def incr(cls):
print cls.var
cls.var+=1
class b(a):
def func(self):
super(b,self).incr()
class c(b):
def func(self):
super(c,self).incr()
t = a()
t1 = b()
t2 = c()
t1.func()
t1.func()
t1.func()
t2.func()
t2.func()
t2.func()`
There is a way to produce the sequence 012345. You have to make sure that the var
of class a
is increased in the incr
method, even when it is called in the subclasses.
To achieve this, increment by a.var += 1
, not by cls.var += 1
.
As pointed out by the other answers, the var
is also inherited to b
and c
.
By using cls.var += 1
both subclasses increase their own var
instead of a
's var
.
class a:
var = 0
@classmethod
def incr(cls):
print(cls.var)
a.var += 1
class b(a):
def f(self):
super().incr()
class c(a):
def f(self):
super().incr()
cb = b()
cc = c()
cb.incr()
cb.incr()
cb.incr()
cc.incr()
cc.incr()
cc.incr()
cb.incr()
cc.incr()
Produces:
0
1
2
3
4
5
6
7
They are inherited from the same class, but the cls
passed to the classmethod
via super is the current class where the method was called from. super
accesses the base class version of the method, but the cls
for the call is the class where the super call was made.
This is one of the subtle differences between doing:
def func(self):
super(c, self).incr() # same as a.__dict__['incr'].__get__(self, type(self))()
and:
def func(self):
a.incr()
You can confirm this by printing the current cls
in your incr
method in both cases:
def incr(cls):
print cls
...
You should never assume that all super
does is make a method call bound to the parent class. It does a lot more.
Keep in mind that when the first augmented assignment +=
is performed, the initial value of var
is read from the base class (since at this point it does not exist in the dict of the subclasses). The updated value is however written to the subclass. Calling super
from the second subclass repeats the same behavior of reading the initial var
value from a
.