В С++ можно создать несколько функций с одинаковым названием но разными типами аргументов. И это будут разные функции.
Во время вызова функции будет выбрана та её версия которая подходит по типам аргументов. Такая конструкция называется параметрический полиморфизм.
Это удобно, когда мы точно не знаем какого типа прилетит аргумент и хотим обработать разные ситуации.
Как мы это поведение можем повторить в 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Если не указать тип одним из этих способов то получите ошибку TypeError.
def func_str(x: str):
print("STR:", x)
Имя новой функции не имеет значения, часто её называют просто "_"
@func.register(list)Если одна функция должна обработать несколько типов, то просто наслаиваем декоратор
def _(x):
print("LIST", x)
@func.register(float)Теперь у нас есть 5 отдельных функций которые вызываются в зависимости от типа передаваемого аргумента. При этом всё выглядит логично и компактно. Обработка каждого случая находится в своей отдельной функции!
@func.register(Decimal)
def _(x):
print(f'{type(x).__name__.upper()}:', x)
>>> func(1)------
INT: 1
>>> func('Python')
STR: Python
>>> func(1.2)
FLOAT: 1.2
>>> func({})
NotImplementedError
◽️ Данный способ работает только с первым аргументом. Все остальные аргументы будут переданы как есть и не участвуют в выборе нужной функции.
◽️ В версии 3.8 доступен декоратор
singledispatchmethod с таким же функционалом но для методов класса.#tricks #libs