Получи случайную криптовалюту за регистрацию!

Наверняка вы знаете что такое перегруженная функция в С++. Есл | Python Заметки

Наверняка вы знаете что такое перегруженная функция в С++. Если нет, то всё просто.
В С++ можно создать несколько функций с одинаковым названием но разными типами аргументов. И это будут разные функции.
Во время вызова функции будет выбрана та её версия которая подходит по типам аргументов. Такая конструкция называется параметрический полиморфизм.
Это удобно, когда мы точно не знаем какого типа прилетит аргумент и хотим обработать разные ситуации.

Как мы это поведение можем повторить в Python? Обычно через проверку типов.

def func(value):
if isinstance(value, int):
return func_int(value)
elif isinstance(value, str):
return func_str(value)
else:
raise NotImplementedError

Не очень красиво
Начиная с версии 3.4 в Python добавили способ делать "перегруженные" функции более элегантно. Это декоратор singledispatch.

Создадим нашу исходную функцию которая по умолчанию выбрасывает ошибку.

@singledispatch
def func(value)
raise NotImplementedError

Декоратор добавил для объекта func новую функцию register() с помощью которой можем регистрировать перегруженные функции.
В качестве аргумента указывайте тип который данная функция обрабатывает

@func.register(int)
def func_int(x):
print("INT:", x)

Вместо указания типа в аргументах можно использовать аннотации аргумента функции

@func.register
def func_str(x: str):
print("STR:", x)

Если не указать тип одним из этих способов то получите ошибку TypeError.

Имя новой функции не имеет значения, часто её называют просто "_"

@func.register(list)
def _(x):
print("LIST", x)

Если одна функция должна обработать несколько типов, то просто наслаиваем декоратор

@func.register(float)
@func.register(Decimal)
def _(x):
print(f'{type(x).__name__.upper()}:', x)

Теперь у нас есть 5 отдельных функций которые вызываются в зависимости от типа передаваемого аргумента. При этом всё выглядит логично и компактно. Обработка каждого случая находится в своей отдельной функции!

>>> func(1)
INT: 1
>>> func('Python')
STR: Python
>>> func(1.2)
FLOAT: 1.2
>>> func({})
NotImplementedError

------
Данный способ работает только с первым аргументом. Все остальные аргументы будут переданы как есть и не участвуют в выборе нужной функции.
В версии 3.8 доступен декоратор singledispatchmethod с таким же функционалом но для методов класса.

#tricks #libs