I have a collection of classes, A1, A2, A3 etc, which all have method m()
. I also have class B with method m()
. I want to easily be able to create classes C1, C2, C3 etc. which call m()
from class B, while also having all other properties of A1, A2, A3 etc...
The issue I'm having, however, is that in class C1 the method m()
from class B should call m()
from the class A1.
I'm having a hard time putting into words what I want, but the the way I'm currently thinking about doing this, is using mixins. C1 would inherit from A1, with a mix-in of B. However, I don't know how to make m()
in B call the correct m()
from one of the A classes.
So, my two questions:
Edit: As requested, a concrete example:
The method m(p)
in A1, A2, A3 etc all calculates a matrix M
, for some parameters p
. I want to create classes C1, C2, C3 etc, which behave in the same way as A1, A2, A3, except for method m()
. The new method m()
takes a longer list of parameters p
, of size N, and we calculate A*.m()
N times and then return the sum.
The code to calculate the sum of m()
is the same for all of the A* classes. In the proposed mix-in solution above, the summing code would be in B. Both B and A1 would be inherited to form C1. However, the method m()
in C1
from B would have to call A1.m()
.
I think you just need super
which redirects the call to a parent or sibling class (depending on the MRO).
For example:
class A1(object):
def m(self):
print('Calling method m of class A1')
self.data *= 2
class A2(object):
def m(self):
print('Calling method m of class A2')
self.data *= 3
class A3(object):
def m(self):
print('Calling method m of class A3')
self.data *= 4
class B(object):
def m(self, p):
print('Calling method m of class B')
for i in range(p):
# You haven't specified which python you are using so I assume
# you might need to most explicit variant of super().
# Python3 also allows just using super().m()
super(B, self).m()
class C1(B, A1):
def __init__(self, value):
self.data = value
Just testing it:
a = C1(10)
a.m(10)
prints:
Calling method m of class B
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
Calling method m of class A1
and the saved value:
a.data
# returns 10485760
defining other C
works too:
class C2(B, A2):
def __init__(self, value):
self.data = value
a = C2(10).m(2)
#Calling method m of class B
#Calling method m of class A2
#Calling method m of class A2
class C3(B, A3):
def __init__(self, value):
self.data = value
a = C3(10).m(1)
#Calling method m of class B
#Calling method m of class A3
Of course you want another logic and probably need to return values from .m()
instead of modifying in-place but I think you can work them out for yourself.
The word you were looking for is probably MRO (method resolution order). Hope this helps you.
Also of interest could be the documentation of super
(Python2), super
(Python3).
And you can always check the MRO
of a class by calling the .mro()
method:
print(C1.mro())
[<class '__main__.C1'>, <class '__main__.B'>, <class '__main__.A1'>, <class 'object'>]
So python starts by checking if C1
has a method m
and if not checks B
. B
has one so it is executed. The super
call then just goes again into the MRO
and checks if the next class (A1
) has a method m
, which is then executed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With