I built a matrices calculator and I want to make one mul method for multiplication by scalar And another one for multiplication by other matrix. I have an if- else block but I prefer it to be in two different methods but i want both of them to work with the * operator . How should i do it?
2 Answers
You can use __mul__ (*) and __matmul__ (@) or, if you want to use just one operator without an if, use singledispatchmethod (Python 3.8+).
import functools class Matrix: @functools.singledispatchmethod def __mul__(self, other): raise NotImplementedError(other) @__mul__.register def _(self, other: int): print('int') @__mul__.register def _(self, other: str): print('str') Matrix() * 1 # 'int' Matrix() * 'a' # 'str' Comments
functools.singledispatchmethod seems like a fit for what you're describing. The other example uses parameter annotation to specify the types, or they can be specified as parameters to the decorators:
>>> class Foo: ... def __init__(self, value): ... self._value = value ... ... @functools.singledispatchmethod ... def __mul__(self, other): ... print("hmm...") ... ... @__mul__.register(int) ... def _(self, other): ... print("Using the int version.") ... return self._value * other ... ... @__mul__.register(list) ... def _(self, other): ... print("Using the list version.") ... return [item * self._value for item in other] ... >>> f = Foo(8) >>> f * 3 Using the int version. 24 >>> f * [1, 2, 3] Using the list version. [8, 16, 24] If using a Python version earlier than 3.8 - (probably better to just do the type checking within a single method without using decorators in this case):
>>> class Foo: ... def __init__(self, value): ... self._value = value ... self.mul = functools.singledispatch(self.mul) ... self.mul.register(int, self.mul_int) ... self.mul.register(list, self.mul_list) ... ... def __mul__(self, other): ... return self.mul(other) ... ... def mul(self, other): ... print("Default mul() called.") ... ... def mul_int(self, other): ... print("Using the int version.") ... return self._value * other ... ... def mul_list(self, other): ... print("Using the list version.") ... return [item * self._value for item in other] ... >>> f = Foo(3) >>> f * 7 Using the int version. 21 >>> f * [1, 2, 3] Using the list version. [3, 6, 9] >>>
__mul__(*) and__matmul__(@).functools.singledispatchcomes to mind...__mul__here but maybe this similar question about__add__will help you. Though sadly it seems that the solutions there won't help you define two different methods.