Method overloading refers to defining multiple methods with the same name but different signatures (parameters) within the same class.
In Python, method overloading is not supported in the traditional sense like in some other languages (e.g., Java or C++), but we can simulate it by using default arguments or by checking the type and number of arguments within the method. In this article, we will discuss different techniques to achieve method overloading-like behavior in Python.
Method Overloading in Python
There are multiple techniques that we can use for method overloading in Python.
- Default Arguments – We define parameters with default values. Default values allow flexibility with fewer arguments.
- Variable-Length Arguments (
*args
and**kwargs
) – This helps to handle an arbitrary number of arguments. - Type Checking with
isinstance
– Handles different types within the same method. - Function Dispatching with
functools.singledispatch
– Overload based on the type of the first argument. - Custom Logic – Write custom methods that handle different parameter combinations.
- External Libraries – Use libraries like
multipledispatch
for more advanced overloading. Usingmultipledispatch
provides the true method overloading very similar to method overloading in other programming languages.
Method Overloading – Using Default Arguments
By providing default values for parameters, a method can be called with different numbers of arguments.
Example of Method Overloading Using Default Arguments
class MathOperations:
def add(self, a, b=0, c=0): # default values to b & c parameters
return a + b + c
math_op = MathOperations()
print(math_op.add(15)) # Output => 15 (one argument)
print(math_op.add(5, 30)) # Output => 35 (two arguments)
print(math_op.add(5, 30, 25)) # Output => 60 (three arguments)
In this example, add(self, a, b=0, c=0)
method has three parameters a
, b
& c
. b
& c
are given default value 0. because of parameters default value, we can call this method either using one argument or two arguments or three arguments.
*args
and **kwargs
)
Method Overloading – Using Variable-Length Arguments (We can use *args
for a variable number of positional arguments and **kwargs
for keyword arguments to handle different method signatures.
- Use
*args
for variable number of positional arguments - Use
**kwargs
for variable number of keyword arguments
Example with *args
class MathOperations:
def add(self, *args): # *args allows variable number of arguments
sum = 0
for num in args:
sum += num
return sum
math_op = MathOperations()
print(math_op.add(15)) # Output => 15 (one argument)
print(math_op.add(5, 30)) # Output => 35 (two arguments)
print(math_op.add(5, 30, 25)) # Output => 60 (three arguments)
In this example, we have defined a function add(self, *args)
which takes variable number of arguments. We are loop through the number of arguments and calculate the total sum. We can call this method using n
number of arguments. We are calling this method using one argument or two arguments or three arguments.
Example with *args
and **kwargs
class MathOperations:
def operation(self, *args, **kwargs): # **kwargs allows variable number of keyword arguments
if kwargs.get('operation') == 'multiply': # Perform multiplication
result = 1
for num in args:
result *= num
return result
else: # Default to addition
result = 0
for num in args:
result += num
return result
math_op = MathOperations()
print(math_op.operation(2, 3)) # Output => 5 (default: sum)
print(math_op.operation(2, 3, operation='multiply')) # Output => 6 (multiplication)
In this example, we have defined a function operation(self, *args, **kwargs)
which takes variable number of positional arguments and variable number of keyword arguments. **kwargs
arguments can be used to handle multiple scenarios. Based on the key-value pair given for **kwargs
, we can perform different operations. math_op.operation(2, 3, operation='multiply')
calls with 2 positional arguments and 1 keyword argument.
isinstance
)
Method Overloading – Using Type Checking (Using isinstance
we can check the types of the arguments inside the method and decide what action to taken based on that.
Syntax – isinstance(variable, datatype)
=> This returns True
of variable is of same datatype and False
if variable if of different datatype.
# Method Overloading - Using Type Checking (isinstance)
class InstanceOperations:
def concat_or_multiply(self, a, b):
if isinstance(a, str) and isinstance(b, str): # check for both parameter value as str
return a + b # If str, perform concatenation
elif isinstance(a, int) and isinstance(b, int): # check for both parameter value as int
return a * b # If int, perform multiplication
else:
raise "UnsupportedTypesError" # error, if both parameters are of different type
instance_op = InstanceOperations()
print(instance_op.concat_or_multiply(5, 10)) # Output: 50
print(instance_op.concat_or_multiply("Python", "@shbytes.com")) # Output: Python@shbytes.com
In this example, concat_or_multiply(self, a, b)
function takes two arguments and isinstance(variable, datatype)
checks for the instance type of each argument. Based on either both the arguments are str
, performs concatenation and if both arguments are int
then it performs multiplication.
functools.singledispatch
)
Method Overloading – Using Function Dispatching (Python’s functools.singledispatch
allows us to overload a function based on the type of the first argument. It doesn’t allow overloading based on multiple arguments but works well for single-argument functions.
@singledispatch
=> Single-dispatch generic function decorator. Transforms a function into a generic function, which can have different behaviors depending upon the type of its first argument. The decorated function acts as the default implementation, and additional implementations can be registered using theregister()
attribute of the generic function.@method_name.register(int)
=> This registers givenmethod_name
forint
datatype argument@method_name.register(str)
=> This registers givenmethod_name
forstr
datatype argument
# Method Overloading - Using Function Dispatching (functools.singledispatch)
from functools import singledispatch # import singledispatch from functools module
@singledispatch # Single-dispatch generic function decorator
def add(a): # define default definition for add(a) function
raise NotImplementedError("Unsupported type")
@add.register(int) # register add(variable) function for int datatype argument
def _(a): # function definition for int datatype argument
return a + 10
@add.register(str) # register add(variable) function for str datatype argument
def _(a): # function definition for str datatype argument
return a + "@shbytes.com"
print(add(15)) # Output: 25
print(add("PowerBI")) # Output: PowerBI@shbytes.com
@singledispatch
onadd(a)
defines a dispatch function with default definition foradd(a)
function@add.register(int)
registers add(a) function forint
datatype argument and_(a)
provides function definition in case ofint
datatype argument.@add.register(str)
registers add(a) function forstr
datatype argument and_(a)
provides function definition in case ofstr
datatype argument.
Method Overloading – Using Custom Logic
We can implement custom logic that handles different combinations of arguments or types within a single method. Custom logic implementation is very similar to default arguments.
# Method Overloading - Using Custom Logic
class MathOperations:
def add(self, a, b=None, c=None): # function definition with b & c default to None
if b is None and c is None: # check if b & c both are None
return a
elif c is None: # check if c is None
return a + b # addition of 2 parameters
else:
return a + b + c # addition of 3 parameters
math_op = MathOperations()
print(math_op.add(50)) # Output: 50 (one argument)
print(math_op.add(50, 20)) # Output: 75 (two arguments)
print(math_op.add(50, 20, 45)) # Output: 115 (three arguments)
multipledispatch
)
Method Overloading – Using External Libraries (We can use third-party libraries like multipledispatch
to achieve true function/method overloading based on the number and types of arguments.
pip install multipledispatch
=> Install multipledispatch
module
# Method Overloading - Using External Libraries (multipledispatch)
from multipledispatch import dispatch # import dispatch from multipledispatch module
class MathOperations:
@dispatch(int, int) # define function for both parameters int
def add(self, a, b): # function definition for both parameters int
return a + b
@dispatch(str, str) # define function for both parameters str
def add(self, a, b): # function definition for both parameters str
return a + " " + b
@dispatch(int, str) # define function for parameters int & str
def add(self, a, b): # function definition for parameters int & str
return "Unsupported datatype"
math_op = MathOperations()
print(math_op.add(50, 10)) # Output: 60
print(math_op.add("PowerBI", "@shbytes.com")) # Output => PowerBI @shbytes.com
print(math_op.add(10, "random")) # Output => Unsupported datatype
@dispatch(int, int)
=> Annotation used on function for both parametersint
@dispatch(str, str)
=> Annotation used on function for both parametersstr
@dispatch(int, str)
=> Annotation used on function for parametersint
&str
Summary
In this article, we learned about various techniques for Method Overloading in Python. Following techniques were discussed:
- Method Overloading in Python
- Method Overloading – Using Default Arguments
- Method Overloading – Using Variable-Length Arguments (*args and **kwargs)
- Method Overloading – Using Type Checking (isinstance)
- Method Overloading – Using Function Dispatching (functools.singledispatch)
- Method Overloading – Using Custom Logic
- Method Overloading – Using External Libraries (multipledispatch)
Code – Github Repository
All code snippets and programs for this article and for Python tutorial, can be accessed from Github repository – Comments and Docstring in Python.