Learning Python- Intermediate course: Day 41, Inheritance in Python

Today we will learn about inheritance in Python

Inheritance

Inheritance provides Code Reusability. We do not need to write the same piece of code again and again for various subclasses. This increases Flexibility of the code. This means that subclasses can be formed without altering the original classes.

The inherited class can use functions and variables of the derived class

Syntax.

Classes can be inherited by passing the name of the superclass to the brackets class inherited(master)

Let us see an example below to demonstrate inheritance in pyuthon

class sample():
 a=2
 b=3
 def fun(self):
     print("Hello world")

class sample2(sample):
    def fun2(self):
        print(self.a+self.b)

mysample2=sample2()
mysample2.fun()
mysample2.fun2()
Hello world
5

Explaination

Here, sample() is the masterclass and sasmple2 is the derived class. The derived class sample2 inherits the master class as we pas the name of the master class into the derived class bracket.

  • class sample2(): This syntax will create class sample2
  • class sample2(sample): This syntax will create a class sample2 and make it inherit the class sample

Once the class sample2 inherits sample, it can use it's attributes (like here a and b) in it's body. This is why no errors were generated when we used to variables a and b directly in the function fun2. The values fir a and b were assigned in the master class (sample2 itself ands need not be assigned again . This is an example of code reuse and information hiding

The derived class sample2 can also use the functions declared in the master class. This is how the function fun could be used and run successfully.

I hope you do not have any more doubts, if you have, please feel free to post them in the comments below.

Inheritance of constructors.

Constructors are not inherited by default. The example below will make things very clear

class sample():
 a=2
 b=3
 def __init__(self):
     self.a=100
     self.b=50
 def fun(self):
     print("Hello world")

class sample2(sample):
    def fun2(self):
        print(self.a+self.b)

mysample2=sample2()
mysample2.fun()
mysample2.fun2()
Hello world
5

In the above example, you would expect the output to be 150 and not 5. But it is not so. This is because of the fact the constructors of the master class are not inherited by the derived classes by default. This means that sample2.__init__ is not the same as sample.__init__.

Why? Well remember In the previous parts we learnt that if we do not provide a constructor to the class, Python provides one default constructor automatically? Something similar happened in this case. We did not provide any constructor to the sample2 class. So python made a default blank constructor in it's place, which had no relation to the master class.

If we want to add the constructor, we can use the following syntax-

class sample():
 a=2
 b=3
 def __init__(self):
     self.a=100
     self.b=50
 def fun(self):
     print("Hello world")

class sample2(sample):
    def __init__(self):
     super().__init__()
    def fun2(self):
        print(self.a+self.b)

mysample2=sample2()
mysample2.fun()
mysample2.fun2()

Using the super keyword, we can manage the constructors.

Note, even though constructors are not inherited, the arguments of the constructors in both the classes must match. Example shown below

class sample():
 a=2
 b=3
 def __init__(self,var):
     self.a=100
     self.b=50
 def fun(self):
     print("Hello world")

class sample2(sample):
    def fun2(self):
        print(self.a+self.b)

mysample2=sample2()
mysample2.fun()
mysample2.fun2()
Traceback (most recent call last):
  File "main.py", line 14, in <module>
    mysample2=sample2()
TypeError: __init__() missing 1 required positional argument: 'var'

...

class sample():
 a=2
 b=3
 def __init__(self,var):
     self.a=100
     self.b=50
 def fun(self):
     print("Hello world")

class sample2(sample):
    def fun2(self):
        print(self.a+self.b)

mysample2=sample2(3)
mysample2.fun()
mysample2.fun2()
Hello world
150

Exercise What is the output of the following program? and why?

class sample():
 a=2
 b=3
 def __init__(self):
     self.a=100
     self.b=50
 def fun(self):
     print("Hello world")

class sample2(sample):
    def __init__(self):
     a=100
     b=200
    def fun2(self):
        print(self.a+self.b)

mysample2=sample2()
mysample2.fun()
mysample2.fun2()

Solution-
The output is

Hello world
5

This is because self.a=100 and self.b=200 should haver been written in place of a=100 and b=200

Function overloading in Python

What if two functions have the same name in the master class as well as the derived class? Well the answer is simple the function in the derived class will be considered.
This is know as function overloading.

class sample():
 a=2
 b=3
 def __init__(self):
     self.a=100
     self.b=50
 def fun(self):
     print("Hello world")


class sample2(sample):
    def __init__(self):
     super().__init__()
    def fun(self):
        print(self.a+self.b)

mysample2=sample2()
mysample2.fun()
150

If we want to use the function in the previous function, then use the super syntax again.

class sample():
 a=2
 b=3
 def __init__(self):
     self.a=100
     self.b=50
 def fun(self):
     print("Hello world")


class sample2(sample):
    def __init__(self):
     super().__init__()
    def fun(self):
        super().fun()
        print(self.a+self.b)

mysample2=sample2()
mysample2.fun()
Hello world
150

So friends that was all for today. Thank you and hope you are enjoying....

20