Reputation: 611
In Python, I have a class ParentClass. It defines method ParentClass.process(), among the others. ParentClass is inherited by two child classes: ChildA and ChildB. This is a part of the system which goes as a pip wheel. The user should not be able to change the code of the package.
During the execution, the system creates objects of ChildA and ChildB.
Now, I want to give the user of the system ability to change the behavior of .process() method for objects of both ChildA and ChildB.
Obviously, she can do that by redefining ChildA.process() and ChildB.process() but that would be copying of identical behavior twice and overall seems like a very odd approach.
The user could possible inherit her own class from ParentClass and redefine .process() there but that means I need somehow dynamically tell ChildA and ChildB what to inherit.
Also, all classes (ParentClass, ChildA and ChildB) have other methods, apart from .process(), which need to be retained without changes.
Please help me figuring out the most convenient for the user (and the most "pythonic", probably) way of solving this.
Upvotes: 2
Views: 3032
Reputation: 42129
You could use intermediate inheritance to define common overrides as an extension of the base class:
class ParentClass:
def process(self):
print("ParentClass.process() called from",type(self))
class ExtendedParent(ParentClass):
def process(self):
super().process()
print("Common Extension code for A and B",type(self))
class ChildA(ExtendedParent):
pass
class ChildB(ExtendedParent):
pass
a = ChildA()
b = ChildB()
a.process()
# ParentClass.process() called from <class '__main__.ChildA'>
# Common Extension code for A and B <class '__main__.ChildA'>
b.process()
# ParentClass.process() called from <class '__main__.ChildB'>
# Common Extension code for A and B <class '__main__.ChildB'>
If ChildA and ChildB are defined in your package and don't have a .process() method, you could instruct the user of your package to assign methods to these classes directly using a common function that is not in any class:
def extendedProcess(self):
ParentClass.process(self) # this replaces super().process()
print("Common Extension code for A and B",type(self))
ChildA.process = extendedProcess
ChildB.process = extendedProcess
If ChildA and/or ChildB have an override of process() and your user wants to change the behaviour of process() in the parent class, here is one way to do it:
ParentClass_process = ParentClass.process
def extendedProcess(self):
ParentClass_process(self) #call original code
print("Common Extension code for A and B",type(self))
ParentClass.process = extendedProcess
Upvotes: 1
Reputation: 61063
You can use a class method to reassign process
for a particular class
class ParentClass:
def process(self):
print("parent")
@classmethod
def reassign_process(cls, process):
cls.process = process
class ChildA(ParentClass):
def process(self):
print("Child A")
class ChildB(ParentClass):
def process(self):
super().process()
print("Child B")
p = ParentClass()
ca = ChildA()
cb = ChildB()
p.process()
# parent
ca.process()
# Child A
cb.process()
# parent
# Child B
def new_parent_process(self):
print("New parent")
ParentClass.reassign_process(new_parent_process)
def new_childa_process(self):
print("New child A")
ChildA.reassign_process(new_childa_process)
p.process()
# New parent
ca.process()
# New child A
cb.process()
# New parent
# Child B
Upvotes: 1