Skip to content

singledispatchmethod dispatches on first argument to instance-bindable method called from class level #143535

Description

@johnslavik

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.13bugs and security fixes3.14bugs and security fixesstdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions