Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Python singledispatch: dispatch follows the first argument’s type

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

Singledispatch chooses a registered implementation from the runtime type of the first positional argument.

Download Python source kit

Operation contract

The default receipt encoder rejects unsupported types. The integer implementation has an exact-type and amount check, while a Boolean registration explicitly rejects bool before its int inheritance can select the numeric route. A text implementation only accepts a small ASCII decimal representation and forwards the converted value to the same integer rule. This keeps two accepted input formats behind one amount contract.

Failure and ownership boundary

Dispatch is not schema validation. Registering int does not imply that every int subclass or every integer magnitude is a valid amount. Other arguments do not participate in singledispatch selection. A broad object registration changes the fallback, and extension registration is a trusted code action. Python first-class functions: dispatch through an explicit operation registry, Python type conversion: parsing success is not field validity and Python __init_subclass__: validate declarations without a custom metaclass explain those boundaries.

Working program

python
from functools import singledispatch

@singledispatch
def encoded_amount(amount):
    raise ValueError("unsupported representation")

@encoded_amount.register(int)
def encode_integer(amount):
    if type(amount) is not int or not 0 <= amount <= 1000:
        raise ValueError("bounded exact integer")
    return f"minor:{amount}"

@encoded_amount.register(bool)
def reject_boolean(amount):
    raise ValueError("boolean amount")

@encoded_amount.register(str)
def encode_text(amount):
    if not 1 <= len(amount) <= 4 or any(character not in "0123456789" for character in amount):
        raise ValueError("ASCII amount")
    return encode_integer(int(amount))

print(encoded_amount(125))
print(encoded_amount("75"))
for invalid in (True, 1.5, "-1"):
    try:
        encoded_amount(invalid)
    except ValueError:
        print("representation rejected")

Output

Output
minor:125
minor:75
representation rejected
representation rejected
representation rejected

Costs and limits

Initial dispatch may examine type relationships; subsequent dispatches can use cached decisions. This is not a fixed-cost promise for arbitrary class hierarchies. The four-character text cap bounds conversion work; formatting a general unbounded integer needs a separate cost policy.

Common Mistakes

  • bool is an int subclass, so numeric registration needs a Boolean policy.
  • singledispatch does not inspect all arguments or enforce annotated types.

Connected lessons

Python first-class functions: dispatch through an explicit operation registry, Python type conversion: parsing success is not field validity, Python __init_subclass__: validate declarations without a custom metaclass.

python
singledispatch-contract
Storage details