Introduction
In inheritance an object is based on another object. When inheritance is implemented, the methods and attributes that were defined in the base class will also be present in the inherited class. This is generally done to abstract away similar code in multiple classes. The abstracted code will reside in the base class and the previous classes will now inherit from the base class.
Example
Derived class inherits features from the base class, adding new features to it. This results into re-usability of code. Let’s look at an example of inheritance. In the following example, Rocket is the base class and MarsRover is the inherited class.
class Rocket: def __init__(self, name, distance): self.name = name self.distance = distance def launch(self): return "%s has reached %s" % (self.name, self.distance) # Inheriting from the base class class MarsRover(Rocket): def __init__(self, name, distance, maker): Rocket.__init__(self, name, distance) self.maker = maker def get_maker(self): return "%s launched by %s" % (self.name, self.maker) if __name__ == "__main__": x = Rocket("Rocket", "Till stratosphere") y = MarsRover("Mars Rover", "Till Mars", "ISRO") print(x.launch()) print(y.launch()) print(y.get_maker()) # Output Rocket has reached Till stratosphere Mars Rover has reached Till Mars Mars Rover Launched by ISRO
In the above example __init__() method was defined in both classes. When this happens, the method in the derived class overrides that in the base class. This is to say, __init__() in MarsRover gets preference over the same in Rocket. A better option would be to use the built-in function super(). Two built-in functions isinstance()
and issubclass()
are used to check inheritances. Function isinstance() returns True if the object is an instance of the class or other classes derived from it. Each and every class in Python inherits from the base class object.
Composition
In composition, we do not inherit from the base class but establish relationships between classes through the use of instance variables that are references to other objects. Continuing from the above example, below example illustrate composition
class MarsRoverComp(): def __init__(self, name, distance, maker): self.rocket = Rocket(name, distance) # instantiating the base self.maker = maker def get_maker(self): return "%s launched by %s" % (self.rocket.name, self.maker) if __name__ == "__main__": z = MarsRover("Mars Rover2", "till Mars", "ISRO") print(z.launch()) print(z.get_maker())
Multiple Inheritance
When a class derived from more than one base classes, it is called multiple inheritance. In multiple inheritance, the features of all the base classes are inherited into the derived class. The syntax for multiple inheritance is similar to single inheritance.
class Base1: pass class Base2: pass # Derived from classes Base1 and Base2 class MultiDerived(Base1, Base2): pass
Multilevel Inheritance
A class can inherit form a derived class. This is called multilevel inheritance. In multilevel inheritance, features of the base class and the derived class is inherited into the new derived class.
class Base: pass class Derived1(Base): pass class Derived2(Derived1): pass
Method Resolution Order
Every class in Python is derived from the class object. It is the most base type in Python. So technically, all other class, either built-in or user-defines, are derived classes and all objects are instances of object class. In the multiple inheritance scenario, any specified attribute is searched first in the current class. If not found, the search continues into parent classes in depth-first, left-right fashion without searching same class twice.
So, in the below example, MultiDerived class the search order is [MultiDerived, Base1, Base2, object]. It ensures that a class always appears before its parents and in case of multiple parents, the order is same as tuple of base classes.
Search order is also called linearization of derived class and the set of rules used to find this order is called Method Resolution Order (MRO). MRO of a class can be viewed as the __mro__ attribute or mro() method.
class Base1: pass class Base2: pass class MultiDerived(Base1, Base2): pass # Output: True print(issubclass(list,object)) # Output: True print(isinstance("Hello",object)) print(MultiDerived.__mro__) # Output (<class '__main__.MultiDerived'>, <class '__main__.Base1'>, <class '__main__.Base2'>, <class 'object'>)