Implementing Multiple-Inheritance using Python

This tutorial is about the implementation of Multiple-Inheritance in Python, the syntax, program along with an explanation.

Prerequisites: Basic idea of Multiple-Inheritance and implementation of classes in Python (refer: Classes and Objects in Python).

Also read the previous tutorial: Introduction to Multiple Inheritance

The Syntax for Multiple Inheritance

The basic format/syntax for multiple-inheritance in Python is as follows:

class Base_1:     #Base Class 1
    pass

class Base_2:      #Base Class 2
    pass

class Derived(Base_1,Base_2):      #Class that derives from both the above base classes
    pass

The above code contains two base classes. Both of them may have their member functions and data members. The third class, which derives from both these base classes can make use of their data members as well as member functions, as long as they are not private to the respective base classes.

Sample Program for Multiple Inheritance

Now, we take up an example to make things more clear. Consider cricket players. There are broadly three categories – batsmen, bowlers and all-rounders. All-rounders have statistical data records about both batting as well as bowling. In other words, they inherit the characteristics of both categories – batsmen and bowlers.

Section-wise explanation

Let us first define the base classes

class Batsman:
    def __init__(self):
        self.strike_rate = 0.0
        self.total_runs = 0
        self.highest_score = 0
        self.batting_rank = 0
    def get_bat(self,sr,tr,hs,br):
        self.strike_rate = sr
        self.total_runs = tr
        self.highest_score = hs
        self.batting_rank = br
    def disp_bat(self):
        print "Strike Rate:",self.strike_rate
        print "Total Runs:",self.total_runs
        print "Highest Score:",self.highest_score
        print "Batting Rank:",self.batting_rank

This is the Batsman class, which contains identifiers for some of the details about a batsman and two member functions: get_bat – to get the details of an object of batsman class, and disp_bat – to display the details of an object of the batsman class.

In the same way, we define another base class – Bowler with details and functions relating to a bowler.

class Bowler:
    def __init__(self):
        self.wickets_taken = 0
        self.economy = 0.0
        self.hattricks = 0
        self.bowling_rank = 0
    def get_bowl(self,wt,ec,ht,bor):
        self.wickets_taken = wt
        self.economy = wc
        self.hattricks = ht
        self.bowling_rank = bor
    def disp_bowl(self):
        print "Wickets Taken:",self.wickets_taken
        print "Economy:",self.economy
        print "Hattricks:",self.hattricks
        print "Bowling Rank:",self.bowling_rank

So, now that we have both our base classes, we define the derived class

class AllRounder(Batsman,Bowler):
    def __init__(self):
        Batsman.__init__(self)
        Bowler.__init__(self)
        self.allrounder_rank = 0
    def get_all(self,sr,tr,hs,br,wt,ec,ht,bor,ar):
        Batsman.get_bat(self,sr,tr,hs,br)
        Bowler.get_bowl(self,wt,ec,ht,bor)
        self.allrounder_rank = 
    def disp_all(self):
        self.disp_bat()
        self.disp_bowl()
        print "All Rounder Rank:",self.allrounder_rank

As per the syntax, the names of the base classes have been mentioned within parentheses, soon after the name of the class in the class header line

In this class, under the __init__() function, we have explicitly called the __init__ functions of the base classes, so that whenever an object of class -AllRounder is initialised, the instance variables of the base classes for the object will also get initialised. Suppose we create an object – obj of AllRounder, the __init__ method of class AllRounder will be called implicitly, following which, the inherited data members of obj from Batsman and Bowler classes will be initialised when the explicit calls are made to their __init__functions.

After that, we add an allrounder_rank data member. This is specific only to objects of AllRounder class and holds no meaning for objects of Batsman or Bowler class. In this way, we can add specific features to the derived class, without disturbing the base classes.

Similarly, in the get_all and disp_all functions, assign/display data values that belong the base classes by calling the respective inherited member functions, as well as, the ones that are specific to the derived AllRounder class.

Complete Program

Let us now put together the pieces and create an object of the AllRounder class.

class Batsman:
    def __init__(self):
        self.strike_rate = 0.0
        self.total_runs = 0
        self.highest_score = 0
        self.batting_rank = 0
    def get_bat(self,sr,tr,hs,br):
        self.strike_rate = sr
        self.total_runs = tr
        self.highest_score = hs
        self.batting_rank = br
    def disp_bat(self):
        print "\nBATTING DATA\n"
        print "Strike Rate:",self.strike_rate
        print "Total Runs:",self.total_runs
        print "Highest Score:",self.highest_score
        print "Batting Rank:",self.batting_rank      

class Bowler:
    def __init__(self):
        self.wickets_taken = 0
        self.economy = 0.0
        self.hattricks = 0
        self.bowling_rank = 0
    def get_bowl(self,wt,ec,ht,bor):
        self.wickets_taken = wt
        self.economy = ec
        self.hattricks = ht
        self.bowling_rank = bor
    def disp_bowl(self):
        print "\nBOWLING DATA\n"
        print "Wickets Taken:",self.wickets_taken
        print "Economy:",self.economy
        print "Hattricks:",self.hattricks
        print "Bowling Rank:",self.bowling_rank

class AllRounder(Batsman,Bowler):
    def __init__(self):
        Batsman.__init__(self)
        Bowler.__init__(self)
        self.allrounder_rank = 0
    def get_all(self,sr,tr,hs,br,wt,ec,ht,bor,ar):
        Batsman.get_bat(self,sr,tr,hs,br)
        Bowler.get_bowl(self,wt,ec,ht,bor)
        self.allrounder_rank = ar
    def disp_all(self):
        print "\nALL-ROUNDER DATA"
        print "\nAll-Rounder Rank:",self.allrounder_rank
        self.disp_bat()
        self.disp_bowl()

player1 = AllRounder()
player1.get_all(89.7,3024,96,67,101,5.67,4,34,57)
player1.disp_all()

In the main section, we declare player1 as an object of the AllRounder class. We then accept all data values for player1 through the get_all function. Redistribute them to respective base classes (see the function definition). Finally, we display the data for the player1 object.

The output is as follows

multiple inheritance in Python output

Leave a Reply

Your email address will not be published. Required fields are marked *