Method overloading and Operator overloading

Method overloading / constructor (__init__()) overloading : 

Python does not support method overloading.It would be justified to say that , python does not require to support method overloading explicitly as done in other languages like java and c++(varying type of parameters and number of parameters to the functions).
Python is a dynamically typed language so type of parameters of method is decided at execution time and overloading is associated with compile time.That's why in python we write a single constructor (__init__() method) that handles all cases, using either default arguments or type or capability tests.If we want complete freedom of adding more parameters: Python has *args and **kwargs arguments which helps to do so.
  • *args -- tuple of anonymous arguments
  • **kwargs -- dictionary of named arguments
Note:
1.It is not mandatory to call them args and kwargs, that’s just a convention.It’s the * and ** that do the magic.
2. *args and **kwargs can be used both independently and together.

Lets create a class and its multiple instances to understand uses of *args and **kwargs. Open python IDLE and create a file copy following code lines.
import math
class ClassName(object):
    def __init__(self, *argsT, **kwargsD):#*argsV and **kwargsD used instead  
     self.sum = sum(args)
     self.name = kwargs.get('name') #accessing name from dictionary 
     self.address = kwargs.get('address')
Now create two instance of ClassName with different types of arguments.
>>> y = ClassName(1,2,3,4, name='ranjan',address ='Hyderabad')
1,2,3, 4 is of int type passed in *arg tuple and  name='ranjan',address ='Hyde' passed as elements of dictionary **kwargsD. Now display name  and sum from object.
>>> y.name
'ranjan'
>>> y.sum
10
Create second instance with floating type and int type data  and display sum for the same.
>>> y = ClassName(1,2.9,3.0,4,name='nikhil',address ='Hyderabad')
>>> y.sum
10.9

Using *argsT, **kwargsD we can handle need of constructor overloading in python. In some situation when we need independent constructor, factory methods can be used to achieve it, refer this post for more detail.

Method overloading is achieved using default parameters in methods and *args and **kwargs, as we can pass variable number of arguments of different types to a method. Lets write a class to understand how to use parameters with default value in method overloading.
Open python IDLE, create a new file and copy following code.
class Employee(object):
 # __init__ - Constructor of class
 def __init__(self,**kawrgs): 
  self.name = kawrgs.get('name')
  self.employeeId = kawrgs.get('employeeId')
   
 #calculate employee salary method with default values goes here
 def calculateSalary(self, hra =10000, travelExpense = 800 ,
                            hotSkillBonus = 0.0 ,
                            specialAllowance = 25000):
  return hra+travelExpense+hotSkillBonus+specialAllowance
First, we create an object of  Employee class and followed by execute different flavour of calculateSalary().
>>> employee = Employee(name= 'Nikhil', employeeId = '897')
>>> employee.calculateSalary (hra = 12000,hotSkillBonus = 1300)
39100
>>> employee.calculateSalary(hra = 12000,travelExpense = 1200, hotSkillBonus = 1300)
39500
>>> employee.calculateSalary() #No arguments passed, default is used here for all parameters
35800.0

Operator overloading 

In python, built in classes provides natural meaning for many operators. For example, 3+4 perform natural addition and produces 7, [2,4]+[5,6] (Sequence types) perform concatenation and results 
[2, 4, 5, 6]. Now think of , a custom class for which operator(i.e: +) is undefined. It is responsibility of author of that class to provide natural semantics (definition) of that operator to that class using Operator overloading. 
How operator overloading mechanism work ?
For each operator, author has  to implement special method to achieve operator overloading.For example, + operator is overloaded by implementing a method named __add__ , which takes
the right-hand operand as a parameter and returns the result of the expression.
for a + b , call transform to a.__add__(b) , method call on object a. Similarly for multiplication operator (*) , a*b will be converted to a.__mul__(b). 

What will happen when binary operator is applied to two instances of different types ?
Lets say, type1 op type2, in such case python gives preference to first operand of type1 and check whether this class has definition for this operation or not. If definition is not found then it will check with type2 class, whether sufficient definition is available for type2 op type1, if it is found this operation will be performed. However, if no proper definition is found , TypeError exception will be raised. 
Take an example of  2*"Welcome", when we execute this statement in python interpretor, first python check with int class whether it has a proper implementation of  __mul__ which multiply a integer with string.Since, int class does not have such definition, python checks the class definition
for the right-hand operand, in the form of a special method named __rmul__ (i.e., “right multiply”). Since, string class has appropriate definition so __rmul__will be executed and displays 
"WelcomeWelcome" (given string concatenated given no of times ).

Here is the list of operators and special methods to be defined for overloading:
Operator and corresponding special method's


  

Previous: Object oriented programming in python Next:Inheritance in python

1 Comments

Previous Post Next Post