johnslavik · GitHub

In this usage of singledispatchmethod:

from functools import singledispatchmethod
class C:
    @singledispatchmethod
    def d(self, x):
        return "base!"
    @d.register(int)
    def _(self, x):
        return "int!"
print(C.d(C(), 1))

This is what I expected in the output:

int!

But instead this was printed out:

base!

singledispatch and singledispatchmethod don't analyze and adapt argument semantics to the registered callable type, which makes them very nice and simple.

_singledispatchmethod_get always dispatches on args[0] regardless of whether it's bound or unbound, and if it didn't, that would break descriptor support; this facet is crucial for staticmethod (and classmethod) dispatches to work:

from functools import singledispatchmethod
class C:
    @singledispatchmethod
    @staticmethod
    def d(x):
        return "base!"
    @d.register(int)
    @staticmethod
    def s(x):
        return "int!"
print(C.d(1))  # int!

Our tests rely on this and possibly millions of projects rely on this.

I think we could document this explicitly (and backport to 3.13 and 3.14).


Found this while working on GH-143465.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Read the original on github.com ↗