A decorator is essentially a wrapper that takes a packed function as an argument and returns another function.
As indicated in the accepted answer, singledispatch returns a wrapper that takes the first argument as a registered type - self in instance methods.
As shown in this answer, in such cases, you can write another wrapper so that the monkey fixes the decorator. But such hacker fixes are not always the best option.
As with any other function, you can call the wrapper and pass arguments to it explicitly, which seems easier, clearer, and easier to read if this type of method is rarely overloaded in a package.
from functools import singledispatch class TestClass(object): def __init__(self): self.test_method = singledispatch(self.test_method) self.test_method.register(int, self._test_method_int) self.test_method.register(list, self._test_method_list) def test_method(self, arg, verbose=False): if verbose: print("Let me just say,", end=" ") print(arg) def _test_method_int(self, arg): print("Strength in numbers, eh?", end=" ") print(arg) def _test_method_list(self, arg): print("Enumerate this:") for i, elem in enumerate(arg): print(i, elem) if __name__ == '__main__': test = TestClass() test.test_method(55555) test.test_method([33, 22, 11])
There is another module, multipledispatch (not standard, but included in Anaconda and without any non-standard dependencies), which, as the name implies and unlike singledispatch , allows multimethods.
In addition to the Dispatcher objects with singledispatch -compatible, it provides a dispatch decorator that hides the creation and management of these objects from the user.
The dispatch decorator uses the function name to select the appropriate Dispatcher object to which it adds a new signature / function. When it encounters a new function name, it creates a new Dispatcher object and saves the name / dispatcher pair in the namespace for future use.
For example:
from types import LambdaType from multipledispatch import dispatch class TestClass(object): @dispatch(object) def test_method(self, arg, verbose=False): if verbose: print("Let me just say,", end=" ") print(arg) @dispatch(int, float) def test_method(self, arg, arg2): print("Strength in numbers, eh?", end=" ") print(arg + arg2) @dispatch((list, tuple), LambdaType, type) def test_method(self, arg, arg2, arg3): print("Enumerate this:") for i, elem in enumerate(arg): print(i, arg3(arg2(elem))) if __name__ == '__main__': test = TestClass() test.test_method(55555, 9.5) test.test_method([33, 22, 11], lambda x: x*2, float)