Functools: Dispatches and Ordering

  • Single dispatch: handle different types of arguments differently.
  • Total ordering: similar to operator overloading in other languages.

singledispatch


from functools import singledispatch


@singledispatch
def handle_error(error):
    raise NotImplementedError("can't handle error")


@handle_error.register(TypeError)
def _(error):
    print("Handling TypeError")
    print(error)


@handle_error.register(ValueError)
def _(error):
    print("Handling ValueError")
    print(error)

With this, we can handle any type of error that we want. We define a default behavior with @singledispatch and additional ones with @handle_error.register. We don't need to name those additional dispatches.

singledispatchmethod

singledispatch only checks the type of the first argument. With this one, we can use specific methods depending on the type of input, for example. Much cleaner than using if else everywhere.


class MyNum:
    def __init__(self, num):
        self.num = num

    @singledispatchmethod
    def add_it(self, another):
        raise NotImplementedError("can't add two things")

    @add_it.register(int)
    def _(self, another):
        self.num += another

    @add_it.register(str)
    def _(self, another):
        self.num += int(another)

    @add_it.register(list)
    def _(self, another):
        for item in another:
            self.add_it(item)

totalordering

What it does is that it helps fill in missing comparison methods for your class. Without it, comparison would solely be based on the length of the value, not the actual value.


from functools import total_ordering


@total_ordering
class BadInt:
    def __init__(self, value):
        self.value = value

    def __eq__(self, other):
        if isinstance(other, int | BadInt):
            return len(str(self.value)) == len(str(other))
        return NotImplemented

    def __lt__(self, other):
        if isinstance(other, int | BadInt):
            return len(str(self.value)) < len(str(other))
        return NotImplemented