HOWTO · Python

Method Overloading in Python

This tutorial introduces method overloading in Python and its advantages with examples.

On this page

Python does not choose a method or function by matching the number or types of arguments to several definitions with the same name. A later definition replaces the earlier name binding. To support different calls, use one function with optional parameters, branch explicitly on input types, or use a third-party multiple-dispatch package. These are different techniques; only the last selects among registered implementations by argument types.

Does Python Support Method Overloading?

Python does not provide signature-based method overloading by default. If a class defines the same method name more than once, the class keeps the last definition under that name. This differs from operator overloading, where a class can define special methods such as __add__ to customize an operator. It also differs from a single method that accepts an optional argument: that method still has one implementation and decides what to do with the values it receives.

For example, a greeting method can accept a name when one is available and use a default when it is not. This is optional-argument behavior, not two overloads.

Use Default Arguments for Optional Parameters

Use a default value when an input is genuinely optional and the same operation works for both calls. The example defines one method and calls it with and without a name.

Run this example:

class Greeter:
    def greet(self, name="there"):
        print(f"Hello, {name}!")


Greeter().greet()
Greeter().greet("Ada")

The supplied run executed these calls and printed:

Hello, there!
Hello, Ada!

The default argument supplies "there" when the caller omits name; passing a name uses that value instead. For mutable defaults such as lists or dictionaries, use None and create a new value inside the method so calls do not share one mutable object.

Use Type Checks for Different Behaviors

When a small set of input types should trigger different behavior, one function can inspect its inputs and branch explicitly. The function below accepts either two integers or two strings. It rejects other combinations with a clear TypeError, rather than relying on accidental behavior from Python’s + operator.

def combine(left, right):
    if type(left) is int and type(right) is int:
        return left + right
    if type(left) is str and type(right) is str:
        return left + right
    raise TypeError("combine expects two integers or two strings")


print(combine(7, 11))
print(combine("Hello, ", "Python"))

The supplied run executed the example and printed:

18
Hello, Python

This is explicit type checking in one function, not automatic method overloading. Exact type(...) is ... checks exclude subclasses such as bool, which is a subclass of int; use isinstance instead if subclasses should be accepted. The function also intentionally does not accept mixed pairs such as an integer and a string. Extend the branches only when those combinations have a defined meaning for your application.

Use Multiple Dispatch for Type-Based Selection

For type-based selection across several argument types, the third-party multipledispatch package registers implementations against signatures. Install it in the environment where the program will run with pip install multipledispatch. The following example defines functions, not class methods, and registers one signature for three integers and another for three floats:

try:
    from multipledispatch import dispatch
except ImportError:
    print("Install multipledispatch to run this example.")
else:
    @dispatch(int, int, int)
    def multiply(first, second, third):
        return first * second * third

    @dispatch(float, float, float)
    def multiply(first, second, third):
        return first * second * third

    print(multiply(3, 7, 8))
    print(multiply(3.6, 5.9, 9.9))

The supplied run exercised the installation-message fallback and printed:

Install multipledispatch to run this example.

Successful calls to the registered dispatch functions with the dependency installed were not exercised. With the package installed, calls matching the registered signatures select the corresponding function implementation. Only those signatures are registered here; a mixed set of integer and float arguments has no matching registration. Add signatures for combinations your program intends to support, and consider whether the dependency is appropriate for your project.

Choose an Approach Based on the Call Signature

Choose a default argument when callers may omit an input and one implementation can handle both forms. Use explicit type checks when there are only a few intentional behaviors and keeping them in one function makes the rule easy to read. Use multiple dispatch when selection by combinations of argument types is central to the design and the additional dependency is acceptable.

None of these choices automatically makes a program faster or simpler. Keep the supported calls explicit: document defaults, define how each accepted type combination behaves, and provide registrations for every signature the dispatch approach must handle. Python’s ordinary name binding remains the same whichever pattern you choose.