Is there any difference between multimethod and multipledispatch?
Asked Answered
S

2

14

I would like to use overloading in Python. I know it's not possible by design (Python is dynamically typed language), there is quite good thread here on this topic. That's why I could use something like multiple dispatch (multimethods). And I'm thinking about the best solution, that would implement multiple dispatch for any function or class method. Is there any solution that is natively included in Python?

Using singledispatch (added to Python in 3.4) is not enough in my case (because only the type of the first argument is considered and I need multiple).

I also know that I could use keyword arguments (i.e. having single function and drive the behavior by checking all arguments), but it's getting complicated when you have a lot of arguments and combinations.

So far, I was able to find these two libraries (not included in the Python Standard Library):

  • multimethod - provides a decorator for adding multiple argument dispatching to functions, one can use the same style of registration as functools.singledispatch, works well with annotations, can even work with annotated predicates or offers special multimeta namespace for classes
  • multipledispatch - provides also decorator for multiple argument dispatching, does not work with annotations and looks not so powerful to me in comparison with the previous library

The basic usage looks like:

from multimethod import multimethod

@multimethod
def add(x: int, y: int):
    ...

@multimethod
def add(x: str, y: str):
    ...

or

from multipledispatch import dispatch

@dispatch(int, int)
def add(x, y):
    ...

@dispatch(str, str)
def add(x, y):
    ...

This functionality seems very similar.

I have mainly two questions:

  • Does one of those multiple dispatch implementations bring any (dis)advantage over the other? (E.g. supported types, speed, performance, limitations, ...) It seems comparable but I was not sure about this, since the latter (multipledispatch) seems to be more popular (checking GitHub stars) but less maintained (and I would even say less mature).
  • Is there any other solution (even such that is included in the Python Standard Library)?
Shive answered 19/3, 2021 at 16:0 Comment(0)
S
13

My reasons on why multimethod is vastly better compared to multipledispatch

  1. Type information we add into method signature, not in the decorator signature. Doing so, is much intuitive and cleaner.
  2. Type hinting of multimethod is same as expected by static type support/mypy. Now, type annotation becoming common among Developers. So, this helps in both way! Multimethod type hinting is officially same as mypy type hinting
  3. Please note, be it multi method or multiple dispatch, seems they support only non-keyword function call. If you call a function with keywords on the call, both fails. This is disappoint, but they may have more reasons to do so. Please read the guides of respective modules. They talk about keywords based function call, but not very clear, IMO. Hence, Some times I feel, simple type checking in our function would solve all problems at once instead of using multimethod or multiple dispatch. After all, I want, first class solution since function are first class objects.
  4. As I know, there is no solution in the language for Polymorphism/function overloading. But multimethod look Pythonic and native. I just like it. Further, multimethod also support single dispatch, though I never felt need of it.
  5. Thank you for your question. You have already answered. I was unaware of exact difference until I read your question. And you have already provided answer. Thank you for the Question.
Shanks answered 11/9, 2021 at 15:12 Comment(2)
As for 3, the biggest multiple dispatch language I can think of, Julia, also only dispatches on positional arguments. The reason is ambiguity. Take the methods f(x: int, y: str): return 1 and f(y: str, x: int): return 2. You can differentiate these by argument order f(1, "one") vs f("one", 1), but keywords abandon order and are thus ambiguous f(y = "one", x = 1). The only way to "fix" this would be to force the user to adhere to some argument name order. Correct me if I'm wrong, but I also can't think of a static language with function overloading that does it for named parameters.Filthy
Thank you for your points, I definitely agree with the type annotation stuff. I will mark your answer as accepted for now since it really seems there is no other solution and that multimethod is better compared to multipledispatch lib.Shive
C
2

In addition to the accepted answer, I would also add...

  1. The multimethod package works great with deferred type hints in the signature, whereas multipledispatch does not. For example...
@multimethod
def __init__(self, color: "Color"):
    self.hex = color.hex

This also works with from __future__ import annotations, which does the same thing under the hood.

Creamcolored answered 17/5, 2023 at 14:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.