Hi Pythonistas!
Today I'm sharing a Python feature that helps you cleanly overload functions based on the type of the argument, no hacks, no if-else chains which is functools.singledispatch
What Problem Does It Solve?
In Python, you can’t define multiple functions with the same name even if the argument types are different:
def show(x: int): ...
def show(x: str): ... # ❌ This replaces the first one
But what if you want your function to behave differently for different input types? Normally we define a function and do the isinstance check in the code. But we have better solution
The Solution: @singledispatch
from functools import singledispatch
@singledispatch
def show(arg):
print(f"Default: {arg}")
@show.register
def _(arg: int):
print(f"Integer: {arg}")
@show.register
def _(arg: str):
print(f"String: '{arg}'")
@show.register
def _(arg: list):
print(f"List with {len(arg)} items: {arg}")
Python will now call the correct version of show() based on the type of the first argument. If there's no match, it falls back to the base version of the function.
Output
In [2]: show(10)
Integer: 10
In [3]: show("hello")
String: 'hello'
In [4]: show([1, 2, 3])
List with 3 items: [1, 2, 3]
In [5]: show({})
Default: {}
In [6]: show(None)
Default: None
In [7]: show(12.255)
Default: 12.255
In [8]:
Bonus: Class-Based Overloading
From Python 3.8+, use @singledispatchmethod in classes:
from functools import singledispatchmethod
class Printer:
@singledispatchmethod
def show(self, arg):
print(f"Default: {arg}")
@show.register
def _(self, arg: int):
print(f"Int: {arg}")
Output
In [11]: a = Printer()
In [12]: a.show(1)
Int: 1
In [13]: a.show('hello')
Default: hello
In [14]:
Pros of @singledispatch
- Clean: Avoids if isinstance() spaghetti
- Extensible: You can register new types elsewhere even in other modules
- Pythonic: Keeps behavior decoupled and readable
- Safe fallback: Has a default implementation if no type matches
Cons of @singledispatch
- Only dispatches on the first argument not multiple or keyword arguments
- Performance overhead for large numbers of registrations
- Slightly more verbose than simple if isinstance() checks for small scripts
- Less intuitive for beginners compared to traditional function overloading in other languages
Summary
- Overloading Based on first argument type only
- Cleaner than if isinstance() blocks
- Good for Type-based dispatch in APIs/tools
- Comes from functools standard library
When you want clean, type-aware behavior in Python, @singledispatch is your best friend.