Я знаю, что это не Pythonic, чтобы писать функции, которые заботятся о типе аргументов, но бывают случаи, когда просто игнорировать типы просто потому, что они обрабатываются по-разному.Декоратор для перегрузки в Python
Имея кучу isinstance
чеки в вашей функции просто уродливые; есть ли доступный декоратор функций, который позволяет перегружать функции? Что-то вроде этого:
@overload(str)
def func(val):
print('This is a string')
@overload(int)
def func(val):
print('This is an int')
Update:
Вот некоторые замечания, которые я оставил на David Zaslavsky's answer:
С несколько модификаций [с], это будет соответствовать моим целям довольно Что ж. Еще одно ограничение, которое я заметил в вашей реализации, поскольку вы используете
func.__name__
в качестве словарного ключа, вы склонны назвать конфликты между модулями, что не всегда желательно. [Продолжение][продолжение]. Например, если у меня есть один модуль, который перегружает
func
, а другой совершенно не связанный модуль, который также перегружаетfunc
, эти перегрузки будут сталкиваться, потому что функция отправки ДИКТ глобальна. Этот dict должен быть локальным для модуля, каким-то образом. И не только это, оно должно также поддерживать какое-то «наследство». [продолжение][продолж.] Под «наследованием» я имею в виду следующее: скажем, у меня есть модуль
first
с некоторыми перегрузками. Затем еще два модуля, которые не связаны между собой, но каждый импортfirst
; оба этих модуля добавляют новые перегрузки к уже существующим, которые они только что импортировали. Эти два модуля должны иметь возможность использовать перегрузки вfirst
, но новые, которые они только что добавили, не должны сталкиваться друг с другом между модулями. (Это на самом деле довольно трудно сделать правильно, теперь, когда я думаю об этом.)
Некоторые из этих проблем могли бы быть решены, изменяя синтаксис декоратор немного:
first.py
@overload(str, str)
def concatenate(a, b):
return a + b
@concatenate.overload(int, int)
def concatenate(a, b):
return str(a) + str(b)
second.py
from first import concatenate
@concatenate.overload(float, str)
def concatenate(a, b):
return str(a) + b
Хм ... так что в вашем правлении, что именно вы подразумеваете под 'contatenate.overload' в' first.py'? Как написано, это попытается получить доступ к атрибуту 'overload' функции' concatenate', которая не существует в этом примере. –
@DavidZaslavsky Самая первая перегрузка функции должна быть украшена '@ overload', которая вернет вызываемый объект, который имеет и атрибут' overload'. Все последующие перегрузки должны быть украшены этим уже существующим объектом '@ object.overload', поэтому существует только один dict на объект, а не глобальный dict. (Он работает аналогично стандарту '@ property'.) Я напишу реализацию и сообщу вам, когда я опубликую ее. –
Это будет отход от традиционного синтаксиса перегрузки. Но если это то, что вы хотите, посмотрите на [пакет перегрузки] (http://pypi.python.org/pypi/overload/1.1) (который я собираюсь внести в свой ответ). Он использует этот метод. –