I have a couple of child classes that I want to use but they both inherit a method from their parent that doesn't quite behave the way I need it to.
class ParentClass():
def __init__(self, value):
self.value = value
def annoying_funct(self):
print("I don't do quite what's needed and print {0}".format(self.value + 1))
def other_parent(self):
print("I do other useful things my children inherit")
class Child1(ParentClass):
def __init__(self, value, new_value1):
super(Child1, self).__init__(value)
self.new_value1 = new_value1
def other_child1(self):
print("I do useful child things")
class Child2(ParentClass):
def __init__(self, value, new_value2):
super(Child2, self).__init__(value)
self.new_value2 = new_value2
def other_child2(self):
print("I do other useful child things")
I want to overwrite annoying_funct()
as something like this:
def annoying_funct():
print("I behave the way I am needed to and print {0}".format(self.value))
ParentClass
, Child1
and Child2
are from a very complex library (scikit-learn
), so I want to keep all of my wrappers as thin as possible. What would be the cleanest/most pythonic way of getting the functionality of my two child classes while altering the parent class as needed?
My thoughts so far:
Create a new class that inherits from the parent which overwrites the function I don't like and then make wrapper classes for the children that inherit from the new class and the child classes.
class NewParentClass(ParentClass):
def annoying_funct(self):
print("I behave the way I am needed to and print {0}".format(self.value))
class NewChild1(NewParentClass, Child1):
pass
class NewChild2(NewParentClass, Child2):
pass
My areas of confusion:
parentClass
and newParentClass
(eg. def newParentClass():
), but if someone tried to make an instance of newParentClass()
the function wouldn't work because it uses attributes not present in that class (value
). Is that ok if I assume the class will never be used?What I ended up doing was using the concept of a mixin to add my new functionality to the child classes. The resulting code was as follows:
class AnnoyMixin:
def well_behaving_func(self):
print("I behave the way I am needed to and print {0}".format(self.value))
class NewChild1(AnnoyMixin, Child1):
def annoying_funct(self):
return well_behaving_func(self)
class NewChild2(AnnoyMixin, Child2):
def annoying_funct(self):
return well_behaving_func(self)
Functionally, this mostly behaves the same as the code I had proposed in my question, but the modifications help with readability. First, by naming the new parent as a "Mixin" it makes it clear that this class is not designed to stand on its own, but rather is intended to add functionality to another class. Because of this, AnnoyMixin
doesn't need to inherit from ParentClass
, simplifying inheritance for the NewChild
classes.
Second, rather than overwriting annoying_funct
in AnnoyMixin
, we create the new function well_behaving_func
. It is then the NewChild
classes job to overwrite annoying_funct
by calling well_behaving_func
. Functionally, this works more or less the same as if the AnnoyMixin
had over written annoying_funct
, but this way, it is clearer to those reading the code that annoying_funct
is being overwritten in the NewChild
classes.