Brian Brian - 1 month ago 12
Python Question

python multiple inheritance and super

This code works as I expect:

class Person(object):
def __init__(self):
self.HasHeartbeat = True

class InsanePerson(Person):
def __init__(self):
super().__init__()
self.IgnoresReality = True

class DumbPerson(Person):
def __init__(self):
super().__init__()
self.SuperDumb = True

class Trump(InsanePerson,DumbPerson):
def __init__(self):
super().__init__()
self.Name = 'Donald'

print(Trump().__dict__)


gives this:

{'HasHeartbeat': True, 'IgnoresReality': True, 'SuperDumb': True, 'Name': 'Donald'}


but if I simply comment out this one line:

class DumbPerson(Person):
def __init__(self):
#super().__init__()
self.SuperDumb = True


I'd expect the output object to have the same
__dict__
as the original case because
print(Trump.__mro__)
gives the same result in both cases:

(<class '__main__.Trump'>, <class '__main__.InsanePerson'>, <class '__main__.DumbPerson'>, <class '__main__.Person'>, <class 'object'>)


but I instead get this with the commented line case:

{'Name': 'Donald', 'IgnoresReality': True}


Can someone explain why this occurs? Why
super()
doesn't run down the entire
Trump().__mro__
list and invoke
DumbPerson.__init__()
?

wim wim
Answer

It doesn't matter what the Trump.__mro__ is, because that only specifies the order of delegation - it says nothing about whether an object in the chain will delegate the next call or not. If you comment out the super call from DumbPerson, then the invocation of __init__ simply stops there, instead of stopping at Person as it would otherwise.

The design decision for python is sometimes called cooperative multiple inheritance. It's intentional and useful, because the developer is granted control over:

  • Whether the "next in line" is invoked or not.
  • When it is invoked (sometimes you need to call super first, sometimes last).
Comments