I have a base class and a sub class. In the base class I have an instance method which is called in __init__
. In the sub class I have overridden this method. The super()
call in the sub class does not call the original base method but the overridden sub class method. Why?
class BaseClass:
def __init__(self, value):
self.value = value
self.transformed_value = self.create_value(value)
def create_value(self, value):
print("base")
return value + 1
class SubClass(BaseClass):
def __init__(self, value):
super().__init__(value)
def create_value(self, value):
print("sub")
return value + 2
s = SubClass(3)
I expect the print output to be "base", but the actual output is "sub". How can I modify the code to get "base" without explicitly calling BaseClass.create_value(self, value)
in the __init__
of BaseClass
?
Python is dynamically typed. That means when you write
def __init__(self, value):
self.value = value
self.transformed_value = self.create_value(value)
is doesn't matter which class that method belongs to when evaluating self.create_value
: it only matters what the type of self
is when the method is called.
When you call SubClass(3)
, you eventually call SubClass.__init__
, which immediately calls BaseClass.__init__
with an argument of type SubClass
. Since SubClass.create_value
is defined, that's what self.create_value
resolves to.
If, for whatever reason, you insist the BaseClass.__init__
calls BaseClass.create_value
on its self
argument, you have to do so explicitly with BaseClass.create_value(self, value)
. However, that's rarely a good idea. If the type of self
wants a method it overrides to be called, that's its responsibility to do so, by using super
itself:
def create_value(self, value):
rv = super().create_value()
print("sub")
return value + 2 # Or perhaps do something with rv first?