I have a base class with some methods and some (potentially many) child classes which modify some aspects of the base class. Additionally, there is a common modification that I'd like to be able to apply to any of the child classes. This modification involves overriding a method. I feel like there should be a simple OOP approach to achieving this, but I don't know what it is.
Say I have a parent class (Base) and some child classes (A and B):
class Base:
def __init__(self):
self.x = 0
def go(self):
self.x+=1
def printme(self):
print(f'x: {self.x}')
class A(Base): #subclasses Base
def go(self):
self.x-=1
class B(Base): #subclasses Base
def go(self):
self.x-=2
a = A()
b = B()
I want to be able to update the .printme() method of objects like a
or b
but this doesn't work
def printme(self):
print(f'modified printing of x: {self.x}')
a.printme = printme
a.printme() #raises TypeError: printme() missing 1 required positional argument: 'self'
(I've seen this solution but it seems hacky and I think there must be a better way.)
I also can't think of a way to use multiple inheritance: if I write a single subclass of Base with the updated printme() function, then I can't generate objects that have the go() methods of class A
or B
without writing separate subclasses for each of those.
After thinking about it for a while longer, I realized it would be possible to dynamically create a new subclass from any child class and override the method like this:
def with_mod(Class):
class ClassWithMod(Class):
def printme(self):
print(f'new statement: {self.x}')
return ClassWithMod
a = A()
a.printme() #prints "x: 0"
a_mod = with_mod(A)()
a_mod.printme() #prints "new statement: 0"
I tested this code and it works, but is this the "correct" approach or is there a more correct/pythonic OOP approach? What I don't like about this solution is that type(a_mod) is the generic ClassWithMod. I'd like it to still be of type A. (Maybe this means I want to override the method at the instance level rather than the class level?)