Polymorphism in python

The Same function defined on the objects of different types is known as polymorphism.

One Name but multiple forms is the concept of polymorphism.

Example: The Best example for the polymorphism is the operator overloading."+ " acts as arithmetic addition operator and the string concatenation operator.

10+20=30  ##arithmatic addition
Apple+Juice=Applejuice ## string concatenation

Following are the related topics to discuss over polymorphism

1.Overloading :

  • Operator Overloading
  • Method Overloading
  • Constructor Overloading

2.Overriding :

  • Method Overriding
  • Constructor Overriding

3.Pythonic Behaviour :

  • Duck Typing
  • Easier to Ask forgiveness than permission
  • Monkey Patching

Operator Overloading

Using the same operator for multiple purposes is nothing but an operator overloading.

Python provides the support for the operator overloading, but Java Won't support for operator overloading.

Example: The following example demonstrates the use of operator overloading

class Book:
    def __init__(self,pages):
        self.pages=pages
        
    def __add__(self,other):  ##__add__ is the magic method for adding two book objects
        total_pages=self.pages+other.pages
        return total_pages
    
b1=Book(100)
b2=Book(200)
b3=Book(500)
print(b1+b2)
print(b1+b3)
print(b2+b3)

The output is:
operator-overloading-example

Operators and corresponding magic methods

Operator Magic Method
+ __add__()
_ __sub__()
* __mul__()
/ __div__()
// __floordiv__()
% __mod__()
** __pow__()
+= __iadd__()
-= __isub__()
*= __imul__()
/= __idiv__()
//= __ifloordiv__()
%= __imod__()
**= __ipow__()
< __lt__()
<= __le__()
> __gt__()
>= __ge__()
== __eq__()
!= __ne__()

Example : Overloading of > and <= operators for student class objects

class Student:
    def __init__(self,name,marks):
        self.name=name
        self.marks=marks
    def __gt__(self,other):
        return self.marks>other.marks
    
s1=Student("Ashu",100)
s2=Student("Ram",200)
s3=Student("Dimpi",40)
print(s1>s2)
print(s1>s3)   

The output is:
operator-overloading-example-two

Whenever we are implementing __gt__ () method automatically __lt__() method will be implemented

class Student:
    def __init__(self,name,marks):
        self.name=name
        self.marks=marks
    def __gt__(self,other):
        return self.marks>other.marks
    
s1=Student("Ashu",100)
s2=Student("Ram",200)
s3=Student("Dimpi",40)
print(s1>s2)
print(s1>s3) 
print(s1<s2)  

The output is:
implementing-less-than-operator

To use <= operator between the two student objects then we have implement the __le__() method.

class Student:
    def __init__(self,name,marks):
        self.name=name
        self.marks=marks
    def __gt__(self,other):
        return self.marks>other.marks
    def __le__(self,other):
        return self.marks<=other.marks
    
s1=Student("Ashu",100)
s2=Student("Ram",200)
s3=Student("Dimpi",40)
print(s1>s2)
print(s1>s3) 
print(s1<s2)  
print(s1<=s2)

The output is:
implementing-less-than-equal-operator

Example : The following program to demonstrate the overloading of the multiplication operator to work on employee objects.

class Employee:
    def __init__(self,name,salaryPerDay):
        self.name=name
        self.salaryPerDay=salaryPerDay
        
    def __mul__(self,other):
        return self.salaryPerDay*other.workingDays
    
class TimeSheet:
    def __init__(self,name,workingDays):
        self.name=name
        self.workingDays=workingDays
        
    def __mul__(self,other):
        return self.workingDays*other.salaryPerDay    
        
e=Employee("Abhinav",500)
t=TimeSheet("Abhinav",25)
print("This Month Salary:",e*t)
print("This Month Salary:",t*e)

The output is:
implementing-mul-method

Installing pydev with Eclipse

The __str__() Method

Whenever we are trying to print any object reference, internally __str__() method will be called, and the default representation of this method returns the string in the following format:

<__main__.Student object at 0x0000014F076EEEB8>

So, to provide a meaningful representation to our string object, we have to override the ___str__() method in our class.

Example:

class Student:
    def __init__(self,name,rollno,marks):
        self.name=name
        self.rollno=rollno
        self.marks=marks
        
        
s1=Student("Gagan",101,34)
s2=Student("Wilson",109,45)
print(s1)
print(s2)

The output is:
without-implementing-str-method

So, to get the meaningful string representation, we have to implement the __str__() method

class Student:
    def __init__(self,name,rollno,marks):
        self.name=name
        self.rollno=rollno
        self.marks=marks
        
    def __str__(self):
        #return self.name
        return "Name:{},RollNo:{},Marks:{}".format(self.name,self.rollno,self.marks)
        
      
s1=Student("Gagan",101,34)
s2=Student("Wilson",109,45)
print(s1)
print(s2)

The output is:
after-implementing-str-method

We can use + operator to add the two-book(b1+b2) objects, but when we use + operator to add three-book (b1+b2+b3) objects, python will throw an error.

class Book:
    def __init__(self,pages):
        self.pages=pages
        
    def __add__(self,other):  ##__add__ is the magic method for adding two book objects
        total_pages=self.pages+other.pages
        return total_pages
    
b1=Book(100)
b2=Book(200)
b3=Book(500)
print(b1+b2)
print(b1+b2+b3)

The output is:
error-while-adding-three-book-objects

This is because b1+b2 returns the result in int format, but we cannot use the concatenation operator (+) between int and string objects(int+b3)

So to overcome this problem, we can return the addition of two book objects into a book instead of int and then we can apply concatenation between [book(pages)+b3].

And to return the total number of pages in a meaningful format, we have to implement the __str__() method.

class Book:
    def __init__(self,pages):
        self.pages=pages
        
    def __add__(self,other):  ##__add__ is the magic method for adding two book objects
        return Book(self.pages+other.pages)
    
    def __str__(self):
        return "The Total Number of Pages:{}".format(self.pages)
    
    
b1=Book(100)
b2=Book(200)
b3=Book(500)
print(b1+b2)
print(b1+b2+b3)

The output is:
adding-three-book-objects-after-implementing-str-method

We can use the Multiplication operator(*) between the book objects; for this, we have to implement the __mul__() magic method.

class Book:
    def __init__(self,pages):
        self.pages=pages
        
    def __add__(self,other):  ##__add__ is the magic method for adding two book objects
        return Book(self.pages+other.pages)
    
    def __str__(self):  ##implementing strig magic method
        return "The Total Number of Pages:{}".format(self.pages)
    
    def __mul__(self,other):  ##implementing multiplicatio magic method
        return Book(self.pages*other.pages)
    
    
b1=Book(100)
b2=Book(200)
b3=Book(500)
b4=Book(600)
print(b1+b2*b3+b4)

The output is:
implementing-mul-method-between-book-objects

Type Casting

Method Overloading

The python won't support method overloading; hence if we declare multiple methods with the same name and a different number of arguments, because python is going to consider only the last method.

Example:

class Test:
    def method1(self):
        print("no argument")
        
    def method1(self,x):
        print("One argument")
        
    def method1(self,x,y):
        print("two argument")
        
t=Test()
t.method1()    

The output is:
method-overloading

If you consider the above output, python is considering the last method and throwing an error as it required two positional arguments x and y.

And if pass the two-argument value then the above program will execute

class Test:
    def method1(self):
        print("no argument")
        
    def method1(self,x):
        print("One argument")
        
    def method1(self,x,y):
        print("two argument")
        
t=Test()
t.method1(12,23)        

The output is:
python-considering-the-last-method-when-it -is-having-same-multiple-methods

Complex Datatype

Variable-Length Arguments Method

A method that accepts any number of arguments is called a variable-length argument.

The syntax for passing variable length arguments is :

def method1(self,*args)  ##*args is used to pass a variable number of arguments to a function.

Example

class Test:
    def method1(self,*args):
        print("Variable length arguments method")

t=Test()
t.method1()
t.method1(10)
t.method1(10,20)
t.method1(10,20,30)
t.method1(10,20,30,40)
t.method1(10,20,30,40,50)

The output is:
variable-length-argument

The following example demonstrates finding the sum of the numbers by using variable length arguments

class Test:
    def <span class=&quot
0 results
Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions