Course topics

By WebNest Studio

Python Tutorial

Method Overloading in Python

In Java or C++, method overloading means defining several methods with the same name but different parameter lists, and the compiler picks one based on the arguments. Python does not support this directly: a later definition with the same name simply replaces the earlier one.

This lesson shows what happens if you try, and the Pythonic ways to get the same flexibility: default and variable arguments, type-based dispatch with functools.singledispatch and singledispatchmethod, alternative constructors, and typing.overload for type checkers.

Why Classic Overloading Does Not Work

A class body is executed like normal code: def area(self, r) followed by def area(self, w, h) binds the name area twice, and only the last function survives. Calling it with one argument then raises TypeError.

Default Arguments and *args

Most overloading needs are met with optional parameters: def area(self, a, b=None) computes a square when b is missing and a rectangle otherwise. *args and **kwargs handle a variable number of arguments.

Dispatch on Type

functools.singledispatch turns a function into a generic function whose implementation is chosen by the type of the first argument; register implementations with @func.register. For methods, functools.singledispatchmethod dispatches on the first argument after self.

typing.overload

@typing.overload declares several signatures for type checkers and IDEs, followed by one real implementation. It documents the accepted combinations but performs no runtime dispatch.

Examples

The last definition wins

Python
class Calculator:
    def add(self, a, b):
        return a + b

    def add(self, a, b, c):          # replaces the first add
        return a + b + c

calc = Calculator()
print(calc.add(1, 2, 3))
try:
    calc.add(1, 2)
except TypeError as e:
    print("TypeError:", e)
Output
6
TypeError: Calculator.add() missing 1 required positional argument: 'c'

Overloading with default arguments and *args

Python
class Calculator:
    def add(self, *numbers):
        return sum(numbers)

    def area(self, a, b=None):
        return a * a if b is None else a * b

calc = Calculator()
print(calc.add(1, 2), calc.add(1, 2, 3, 4))
print(calc.area(5), calc.area(4, 6))
Output
3 10
25 24

Type-based dispatch with singledispatch and singledispatchmethod

Python
from functools import singledispatch, singledispatchmethod

@singledispatch
def describe(value):
    return f"something: {value!r}"

@describe.register
def _(value: int):
    return f"integer with {len(str(abs(value)))} digits"

@describe.register
def _(value: list):
    return f"list of {len(value)} items"

print(describe(12345), "|", describe([1, 2]), "|", describe(3.5))

class Formatter:
    @singledispatchmethod
    def format(self, value):
        return str(value)

    @format.register
    def _(self, value: float):
        return f"{value:.2f}"

    @format.register
    def _(self, value: dict):
        return ", ".join(f"{k}={v}" for k, v in value.items())

f = Formatter()
print(f.format(7), f.format(3.14159), f.format({"a": 1, "b": 2}))
Output
integer with 5 digits | list of 2 items | something: 3.5
7 3.14 a=1, b=2

typing.overload for precise type hints

Python
from typing import overload

@overload
def parse(value: str) -> int: ...
@overload
def parse(value: bytes) -> str: ...

def parse(value):
    if isinstance(value, bytes):
        return value.decode()
    return int(value)

print(parse("42") + 1, parse(b"hello").upper())
Output
43 HELLO

Common Mistakes

  • Defining several methods with the same name expecting Java-style overloading.
  • Writing long isinstance chains where singledispatch would be clearer.
  • Expecting typing.overload to dispatch at runtime — it only informs type checkers.
  • Using *args everywhere so the function signature no longer documents its inputs.

Key Points to Remember

  • Python keeps only the last definition of a name; there is no classic overloading.
  • Default arguments and *args/**kwargs cover most overloading needs.
  • functools.singledispatch / singledispatchmethod dispatch on argument type.
  • Alternative constructors (@classmethod) replace constructor overloading.
  • typing.overload documents multiple signatures for type checkers.

Practice the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.