Trusted answers to developer questions
Trusted Answers to Developer Questions

Related Tags

python
communitycreator

What is the singledispatchmethod() decorator in Python?

abhilash

Grokking Modern System Design Interview for Engineers & Managers

Ace your System Design Interview and take your career to the next level. Learn to handle the design of applications like Netflix, Quora, Facebook, Uber, and many more in a 45-min interview. Learn the RESHADED framework for architecting web-scale applications by determining requirements, constraints, and assumptions before diving into a step-by-step design process.

The functools module

The functools module in Python allows us to create higher-order functions that interact with other functions. The higher-order functions either return other functions or operate on them to broaden the functions’ scope without modifying or explicitly defining them.

The singledispatchmethod decorator

The singledispatchmethod decorator is used for method classes overloading. The functionality is similar to the singledispatch decorator. However, the dispatch is based on the type of the first non-self or non-cls argument. This allows for the overloading of both the method and the class method.

Example

from functools import singledispatchmethod
class Sum:
@singledispatchmethod
def sumMethod(self, arg1, arg2):
print("Default implementation with arg1 = %s and arg2 = %s" % (arg1, arg2))
@sumMethod.register
def _(self, arg1: int, arg2: int):
print("Sum with arg1 as integer. %s + %s = %s" % (arg1, arg2, arg1 + arg2))
@sumMethod.register
def _(self, arg1: float, arg2: float):
print("Sum with arg1 as float. %s + %s = %s" % (arg1, arg2, arg1 + arg2))
s = Sum()
s.sumMethod(2, 3)
s.sumMethod(2.1, 3.4)
s.sumMethod("hi", 3.4)

Explanation

  • Line 1: The singledispatchmethod decorator is imported from the functools module.

  • Line 3: The Sum class is defined.

  • Lines 6-7: A function named sumMethod is defined in the Sum class. It accepts two arguments, arg1 and arg2. The sumMethod function is decorated with the singledispatchmethod decorator. This is the default implementation of the sumMethod function.

  • Lines 10-11: We register the first implementation of the sumMethod function for which arg1 should be of the integer type. Here, arg1 is annotated with int as its type.

  • Lines 14-15: We register the second implementation of the sumMethod function for which arg1 should be of the float type. Here, arg1 is annotated with float as its type.

  • Lines 18-21: We invoke sumMethod with different types of values for arg1.

  • Line 21: The default implementation of sumMethod will be executed since there is no implementation of sumMethod for the string type.

from functools import singledispatchmethod
class Sum:
@singledispatchmethod
def sumMethod(self, arg1, arg2):
print("Default implementation with arg1 = %s and arg2 = %s" % (arg1, arg2))
@sumMethod.register(int)
def _(self, arg1, arg2):
print("Sum with arg1 as integer. %s + %s = %s" % (arg1, arg2, arg1 + arg2))
@sumMethod.register(float)
def _(self, arg1, arg2):
print("Sum with arg1 as float. %s + %s = %s" % (arg1, arg2, arg1 + arg2))
s = Sum()
s.sumMethod(2, 3)
s.sumMethod(2.1, 3.4)
s.sumMethod("hi", 3.4)

The code above shows how to achieve the same functionality without using annotations. The expected type of arg1 is passed to the register attribute.

Overloading class methods

The @singledispatchmethod decorator supports nesting with other decorators such as @classmethod, @staticmethod, and so on. To allow for dispatcher.register, singledispatchmethod must be the outermost decorator.

Let’s take a look at an example:

from functools import singledispatchmethod
class Educative:
@singledispatchmethod
@classmethod
def newPrint(cls, arg):
print("Default implementation. arg - %s" % (arg, ))
@newPrint.register(int)
@classmethod
def _(cls, arg):
print("Integer implementation. arg - %s" % (arg, ))
@newPrint.register(bool)
@classmethod
def _(cls, arg):
print("Boolean implementation. arg - %s" % (arg, ))
Educative.newPrint(4)
Educative.newPrint(True)
Educative.newPrint("hi")

Explanation

In the code above, we define a class called Educative. Here, the newPrint class method is overloaded using the @singledispatchmethod. We then decorate the newPrint method with the @singledispatchmethod decorator as the outermost decorator.

RELATED TAGS

python
communitycreator

Grokking Modern System Design Interview for Engineers & Managers

Ace your System Design Interview and take your career to the next level. Learn to handle the design of applications like Netflix, Quora, Facebook, Uber, and many more in a 45-min interview. Learn the RESHADED framework for architecting web-scale applications by determining requirements, constraints, and assumptions before diving into a step-by-step design process.

Keep Exploring