Рубрики
Без рубрики

Python 3 – Функция перегрузки с Singledispatch

Получите практические, реальные навыки Python на наших ресурсах и пути

Автор оригинала: Mike Driscoll.

Python довольно недавно добавил частичную поддержку для перегрузки функций в Python 3.4 Отказ Они сделали это, добавив аккуратный маленький декоратор к Functools Модуль называется Singledispatch Отказ Этот декоратор преобразует вашу регулярную функцию в единую рожущую функцию отправки. Обратите внимание, однако, что SingleDispatch происходит только на основе типа первого аргумента. Давайте посмотрим на пример, чтобы увидеть, как это работает!

from functools import singledispatch


@singledispatch
def add(a, b):
    raise NotImplementedError('Unsupported type')


@add.register(int)
def _(a, b):
    print("First argument is of type ", type(a))
    print(a + b)


@add.register(str)
def _(a, b):
    print("First argument is of type ", type(a))
    print(a + b)


@add.register(list)
def _(a, b):
    print("First argument is of type ", type(a))
    print(a + b)


if __name__ == '__main__':
    add(1, 2)
    add('Python', 'Programming')
    add([1, 2, 3], [5, 6, 7])

Здесь мы импортируем Singledispatch от Functools и применим его к простой функции, которую мы называем Добавить Отказ Эта функция является нашей функцией «все» и будет вызывать только в том случае, если ни одна из других украшенных функций не обрабатывает тип переданного типа. Вы отметите, что в настоящее время мы обрабатываем целые числа, строки и списки как первый аргумент. Если бы мы позвонили нашему добавлению функции с чем-то другим, таким как словарь, то он поднимел бы ниотмементироватьЭррра.

Попробуйте запустить код самостоятельно. Вы должны увидеть вывод, который выглядит так:

First argument is of type  
3
First argument is of type  
PythonProgramming
First argument is of type  
[1, 2, 3, 5, 6, 7]
Traceback (most recent call last):
  File "overloads.py", line 30, in 
    add({}, 1)
  File "/usr/local/lib/python3.5/functools.py", line 743, in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
  File "overloads.py", line 5, in add
    raise NotImplementedError('Unsupported type')
NotImplementedError: Unsupported type

Как видите, код работает точно так, как рекламируется. Он вызывает соответствующую функцию на основе типа первого аргумента. Если тип не обрабатывается, то мы поднимаем NotimplementedError. Если вы хотите узнать, какие типы мы в настоящее время обрабатываем, вы можете добавить следующий кусок кода в конец файла, предпочтительнее перед строкой, которая поднимает ошибку:

print(add.registry.keys())

Это распечатает что-то вроде этого:

dict_keys([, , , ])

Это говорит нам, что мы можем обрабатывать строки, целые числа, списки и объекты (по умолчанию). Singlededispatch Decorator также поддерживает укладку декоратора. Это позволяет нам создать перегруженную функцию, которая может обрабатывать несколько типов. Давайте взглянем:

from functools import singledispatch
from decimal import Decimal


@singledispatch
def add(a, b):
    raise NotImplementedError('Unsupported type')


@add.register(float)
@add.register(Decimal)
def _(a, b):
    print("First argument is of type ", type(a))
    print(a + b)


if __name__ == '__main__':
    add(1.23, 5.5)
    add(Decimal(100.5), Decimal(10.789))

Это в основном говорит Python, что одно из добавленных функций перегрузки может обрабатывать поплавок и десятичных данных. Если вы запустите этот код, вы должны увидеть что-то вроде следующего:

First argument is of type  
6.73
First argument is of type  
111.2889999999999997015720510
dict_keys([, , , 

Возможно, вы уже заметили это, но из-за того, как были написаны все эти функции, вы можете уложить декораторы для обработки всех случаев в предыдущем примере и в этом примере в одну перегруженную функцию. Однако в нормальном перегруженном случае каждая перегрузка позвонила бы другой код вместо того же.

Обертывание

Перегрузка функций была в течение довольно некоторого времени на других языках. Приятно видеть, что Python также добавил это. Конечно, некоторые из других языков позволяют мультидисперцу вместо одной отправки, что означает, что они смотрят на более чем один из типов аргументов. Надеюсь, Python добавит эту функциональность в будущем выпуске. Также обратите внимание, что вы можете зарегистрировать лямбдас и ранее существующие функции с singledispatch. Смотрите документацию для полных деталей.

Связанное чтение