Как сделать 2 разных метода __mul__ - PullRequest
3 голосов
/ 02 апреля 2020

Я построил калькулятор матриц, и я хочу сделать один mul метод для умножения на скаляр и другой для умножения на другую матрицу. У меня есть блок if-else, но я предпочитаю использовать два разных метода, но я хочу, чтобы они оба работали с оператором *. Как мне это сделать?

Ответы [ 2 ]

3 голосов
/ 02 апреля 2020

Вы можете использовать __mul__ (*) и __matmul__ (@) или, если вы хотите использовать только один оператор без if, использовать 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'
0 голосов
/ 02 апреля 2020

functools.singledispatchmethod кажется подходящим для того, что вы описываете. Другой пример использует аннотацию параметров для указания типов, или они могут быть указаны как параметры для декораторов:

>>> 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]

Если используется версия Python ранее 3.8 - (вероятно, лучше просто сделать тип проверка в пределах одного метода без использования декораторов в этом случае):

>>> 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]
>>> 
...