Reputation: 142
please help me understand the concept of multiple inheritance here in Python (I am from C# background which does not support multiple inheritance).
I am using Python 3.7.6.
In the below code, the class Apple
inherits the classes ToyFruit
, NaturalFruit
, FakeFruit
and RoboticFruit
. While ToyFruit
, NaturalFruit
, and FakeFruit
inherit Fruit
base class, RoboticFruit
has a different BaseClass
Robot
.
I notice that the RoboticFruit
and Robot
are not at all getting called.
class Fruit:
def __init__(self, name):
print("This is the Fruit __init__ function")
self.test = "BaseClass"
self.name = name
print("Fruit object created")
class NaturalFruit(Fruit):
def __init__(self, name):
print("This is the NaturalFruit __init__ function")
super().__init__(name)
self.type = "Natural"
print("This is a Natural Fruit")
self.test = "NaturalClass"
print("Natural Fruit object created")
class FakeFruit(Fruit):
def __init__(self, name):
print("This is the FakeFruit __init__ function")
super().__init__(name)
self.type = "Fake"
print("This is a Fake Fruit")
self.test = "FakeClass"
print("Fake Fruit object created")
class ToyFruit(Fruit):
def __init__(self, name):
print("This is the ToyFruit __init__ function")
super().__init__(name)
self.type = "Toy"
print("This is the Toy Fruit")
self.test = "ToyClass"
print("Toy Fruit object created")
class Robot:
def __init__(self, name):
print("This is the ROBOT __init__ function")
self.test = "RobotClass"
self.name = name
print("Robot object created")
class RoboticFruit(Robot):
def __init__(self, name):
super().__init__("RoboticFruit")
print("Robotic Fruit")
class Apple(ToyFruit, NaturalFruit, FakeFruit, RoboticFruit):
def __init__(self):
super().__init__("Apple")
print("Apple object created")
apple = Apple()
# print(apple.name)
print(apple.test)
OUTPUT:-
This is the ToyFruit __init__ function
This is the NaturalFruit __init__ function
This is the FakeFruit __init__ function
This is the Fruit __init__ function
Fruit object created
This is a Fake Fruit
Fake Fruit object created
This is a Natural Fruit
Natural Fruit object created
This is the Toy Fruit
Toy Fruit object created
Apple object created
ToyClass
If I swap the order to
class Apple(RoboticFruit, ToyFruit, NaturalFruit, FakeFruit):
Then the ToyFruit
, NaturalFruit
, FakeFruit
and Fruit
__init__
methods are not called at all.
I am not understanding why the RoboticFruit
class constructors are getting skipped.
Upvotes: 1
Views: 187
Reputation: 707
I'm not sure that it returns the result you want, but it could be an option to replace super()
calls to __init__
with hardcoded calls:
class Fruit:
def __init__(self, name):
print("This is the Fruit __init__ function")
self.test = "BaseClass"
self.name = name
print("Fruit object created")
class NaturalFruit(Fruit):
def __init__(self, name):
print("This is the NaturalFruit __init__ function")
Fruit.__init__(self, name)
self.type = "Natural"
print("This is a Natural Fruit")
self.test = "NaturalClass"
print("Natural Fruit object created")
class FakeFruit(Fruit):
def __init__(self, name):
print("This is the FakeFruit __init__ function")
Fruit.__init__(self, name)
self.type = "Fake"
print("This is a Fake Fruit")
self.test = "FakeClass"
print("Fake Fruit object created")
class ToyFruit(Fruit):
def __init__(self, name):
print("This is the ToyFruit __init__ function")
Fruit.__init__(self, name)
self.type = "Toy"
print("This is the Toy Fruit")
self.test = "ToyClass"
print("Toy Fruit object created")
class Robot:
def __init__(self, name):
print("This is the ROBOT __init__ function")
self.test = "RobotClass"
self.name = name
print("Robot object created")
class RoboticFruit(Robot):
def __init__(self, name):
Robot.__init__(self, "RoboticFruit")
print("Robotic Fruit")
class Apple(ToyFruit, NaturalFruit, FakeFruit, RoboticFruit):
def __init__(self):
ToyFruit.__init__(self, "Apple")
NaturalFruit.__init__(self, "Apple")
FakeFruit.__init__(self, "Apple")
RoboticFruit.__init__(self, "Apple")
print("Apple object created")
apple = Apple()
#print(apple.name)
print(apple.test)
# output:
# This is the ToyFruit __init__ function
# This is the Fruit __init__ function
# Fruit object created
# This is the Toy Fruit
# Toy Fruit object created
# This is the NaturalFruit __init__ function
# This is the Fruit __init__ function
# Fruit object created
# This is a Natural Fruit
# Natural Fruit object created
# This is the FakeFruit __init__ function
# This is the Fruit __init__ function
# Fruit object created
# This is a Fake Fruit
# Fake Fruit object created
# This is the ROBOT __init__ function
# Robot object created
# Robotic Fruit
# Apple object created
# RobotClass
Upvotes: 0
Reputation: 707
In case of multiple inheritance, super()
delegates to the next object in the Method Resolution Order (MRO). We can see the MRO of the class Apple
:
print(Apple.__mro__)
# output:
(
<class '__main__.Apple'>,
<class '__main__.ToyFruit'>,
<class '__main__.NaturalFruit'>,
<class '__main__.FakeFruit'>,
<class '__main__.Fruit'>,
<class '__main__.RoboticFruit'>,
<class '__main__.Robot'>,
<class 'object'>
)
So I suppose that RoboticFruit
and Robot
are not called because there is no call like super().__init__(name)
in class Fruit
, which is the previous one to RoboticFruit
in that order (MRO). If you add a call to super()
in Fruit
, it should work correctly:
class Fruit:
def __init__(self, name):
print("This is the Fruit __init__ function")
super().__init__(name)
self.test = "BaseClass"
self.name = name
print("Fruit object created")
Upvotes: 3