Reputation: 1098
I have the following simplified class structure
class A():
def foo(self):
self.bar()
def bar(self):
print("A bar")
class B(A):
def bar(self):
print("B bar")
class C(A):
def bar(self):
print("C bar")
Now I also have a modified version of A
class ModA():
def foo(self):
print("hi")
self.bar()
I now also want a additional versions of B and C that have ModA
as parent class instead of A
.
class ModB(ModA):
def bar(self):
print("B bar")
class ModC(ModA):
def bar(self):
print("C bar")
How do I define ModB
and ModC
without duplicating their entire definition except for the first line that defines the parents?
Upvotes: 1
Views: 62
Reputation: 23753
Based on your toy example here is one way to do it.
class FooBase:
def foo(self):
self.bar()
class FooMod:
def foo(self):
print("hi")
self.bar()
class A(FooBase):
def bar(self):
print("A bar")
class B(FooBase):
def bar(self):
print("B bar")
class C(FooBase):
def bar(self):
print("C bar")
class ModA(FooMod,A):
pass
class ModB(FooMod,B):
pass
class ModC(FooMod,C):
pass
class BadModA(A,FooMod):
pass
for thing in [A,B,C,ModA,ModB,ModC,BadModA]:
thing = thing()
print(thing.foo())
print('**********')
You have to be careful how you order the base classes notice BadModA
doesn't work because it finds the foo
method in FooBase
before looking in FooMod
. You can see that in their Method Resolution Order's
In [15]: ModA.__mro__
Out[15]: [__main__.ModA, __main__.FooMod, __main__.A, __main__.FooBase, object]
In [16]: BadModA.__mro__
Out[16]: (__main__.BadModA, __main__.A, __main__.FooBase, __main__.FooMod, object)
While this works it seems like you could get yourself in trouble. you always have to remember which order to use - maybe someone will comment.
Here is another way, it flattens the structure out a bit, five bases and you mix them up
class FooBase:
def foo(self):
self.bar()
class FooMod:
def foo(self):
print("hi")
self.bar()
class Abar:
def bar(self):
print("A bar")
class Bbar:
def bar(self):
print("B bar")
class Cbar():
def bar(self):
print("C bar")
class A(FooBase,Abar):
pass
class B(FooBase,Bbar):
pass
class C(FooBase,Cbar):
pass
class ModA(FooMod,Abar):
pass
class ModB(FooMod,Bbar):
pass
class ModC(FooMod,Cbar):
pass
Upvotes: 1
Reputation: 12927
It is impossible to answer without knowing what your "slight changes" might be, but in general, look at multi-inheritance - class ModB(ModA, B):
might be what you need.
class ModB(ModA, B):
pass
>>> b = ModB()
>>> b.foo()
hi
B bar
Upvotes: 1