Here is a simplified code of my main code illustrating the behaviour I obtain.
Suppose I have a main class (MAIN) and two classes (A,B) inheriting from it. This main class has a method which is overwriten by A but not by B, which means that B inherits the method from main.
Then I have a class D which inherits from A and from B, and has a method which calls the aforementioned method. From what I have understood in the way multiple inheritance work, if I define D as class D(A,B)
then if A and B have a shared method, calling D.method() will call A.method, and vice-versa (i.e if class D(B,A)
then B.method is called. The following code exemplifies this text.
class MAIN(object):
def __init__(self):
pass
def print(self):
print('HELLO MAIN')
class A(MAIN):
def __init__(self):
pass
def print(self):
print('HELLO A')
class B(MAIN):
def __init__(self):
pass
class C(A,B):
def __init__(self):
pass
def Cprint(self):
self.print()
c = C()
c.Cprint()
class C(B,A):
def __init__(self):
pass
def Cprint(self):
self.print()
c = C()
c.Cprint()
However this code always print 'HELLO A', i.e even in the case class C(B,A)
I don't get a HELLO MAIN as I would expect. What is happening here? Thanks so much in advance
The mro
is (C, A, B, MAIN)
with class C(A, B)
and (C, B, A, MAIN)
with class C(B, A)
. In both cases, A
is before MAIN
. B
doesn't define .print
, so it doesn't matter.
The method uplooks works like this: (pseudo code)
def find_attribute(obj, name):
if name in obj.__dict__:
return obj.__dict__[name]
mro = type(obj).__mro__
for cls in mro:
if name in cls.__dict__:
return cls.__dict__[name] # (Here a bit more magic for descriptors happens)
raise AttributeError(name)
For the classes this is what their __dict__
look like:
MAIN.__dict__ = {"print": <method MAIN.print>}
A.__dict__ = {"print": <method A.print>}
B.__dict__ = {}
C.__dict__ = {"Cprint": <method C.Cprint>}
As you can see, B
does not have a print
defined, so in mro=(C, B, A, MAIN)
the first print
that does get found is in A
.