Задача - нам нужно написать функцию inspect_object
, которая бы печатала различные данные об объекте переданном ей в первом аргументе. Например, если мы знаем, что аргументом является функция, дополнительно мы можем вывести её сигнатуру. У нас есть 2 очевидных варианта реализации, засунуть проверку на тип внутрь функции (куча if
`ов) или же написать по функции на объект.
1-вый вариант:
import types, inspect
def inspect_object(obj):
print "repr:", repr(obj)
if isinstance(obj, types.FunctionType):
print "sign:", (obj.__name__ + inspect.formatargspec(
*inspect.getargspec(obj)))
elif isinstance(obj, types.ModuleType):
print "file:", obj.__file__
И 2-ой:
import inspect
def inspect_object(obj):
print "repr:", repr(obj)
def inspect_func(obj):
print "repr:", repr(obj)
print "sign:", (obj.__name__ + inspect.formatargspec(
*inspect.getargspec(obj)))
def inspect_module(obj):
print "repr:", repr(obj)
print "file:", obj.__file__
Сразу скажу, оба они ужасны. Но первый хоть и плохо расширяем, но всё же более предпочтителен, так как не требует знания типа объекта при вызове функции.
Вот тут то и не хватает перегрузки функций, которая элегантным образом решила бы проблему. В Python 3.0 собирались ввести стандартный модуль overloading но дело не заладилось (подробности). Судя по PEP`у, в модуле должно было быть реализовано много вкусностей (обобщенные функции, перегрузка, интерфейсы и т.д.). Библиотека должна была использовать аннотации функций появившиеся в новой версии python'а, а смотрелось бы это на нашем примере так:
import types, inspect
from overloading import overload
# обобщенная функция
def inspect_object(obj):
print "repr:", repr(obj)
@overload
def inspect_object(module: types.ModuleType):
print "repr:", repr(module)
print "file:", module.__file__
@overload
def inspect_object(function: types.FunctionType):
print "repr:", repr(function)
print "sign:", (function.__name__ + inspect.formatargspec(
*inspect.getargspec(function)))
Этот код понятен и легко расширяем, ведь легче написать новую специализированную функцию чем рыться во всех этих if
`ах. (более аргументированные объяснения, чем подход с специализированными функциями лучше, ручного выбора с помощью if
`ов, можно почитать в любой хорошей книжке по C++ или в том же PEP-3107)
Но к сожалению библиотеку так и не реализовали до базового функционала.
Мне давно была интересна эта тема и после того как я узнал что PEP всё таки отложили на неопределённое время, я решился на написание собственного велосипеда реализации. В ней нет и половины возможностей и расширяемости первоисточника, но я писал её скорее для фана. В моём представлении она должна выполнять свою основную задачу, добавлять в язык перегрузку функций, основанную на типах аргументов, максимально близкую к реализации оной из C++. Т.е. от идеи включения в библиотеку реализации интерфейсов и прочего функционала, я отказался, сосредоточившись на перегрузке. Так как писал я библиотеку на чистом python`е и поиск функций происходит в runtime, то старался максимально сократить время поиска среди кандидатов, подходящей функции (Phillip J. Eby, автор PEP`а и библиотеки PEAK для оптимизации использовал Bytecode Assembler, а это сильная магия:)). Всё таки Python 3.0 еще будущее, а настоящим сейчас является ветка 2.x, в которой нет аннотаций для функций. Так что синтаксис немного видоизменился, тип аргумента передаётся декоратору overload
в качестве параметра, первый тип ассоциируется с первым параметром декорируемой функции, второй со вторым, и т.д.
Наш пример, использующий библиотеку, выглядит так:
import types, inspect
from overloading import overload
# обобщенная функция
def inspect_object(obj):
print "repr:", repr(obj)
@overload(types.ModuleType)
def inspect_object(module):
print "repr:", repr(module)
print "file:", module.__file__
@overload(types.FunctionType)
def inspect_object(function):
print "repr:", repr(function)
print "sign:", (function.__name__ + inspect.formatargspec(
*inspect.getargspec(function)))
В случае если вы не хотите типизировать один из параметров функции, можно поставить в место типа object
, ведь библиотека поддерживает полиморфизм.
Не буду пересказывать все достоинства и недостатки библиотеки, так как всё это разжевано в документации, для заинтересовавшихся ссылка на страницу проекта
вторник, 19 мая 2009 г.
Перегрузка функций в python
Так уж случилось что пришел я к python'у из мира С++, Как и многие "эмигранты" в начале своего изучения языка, я пытался писать на нем как на С++. Именно тогда мне не хватало перегрузки функций, особенно это чувствовалось в конструкторах. Позже, освоившись с дизайном языка, в таких случаях я стал использовать именованные параметры (keyword parameters) или просто начал давать разные имена функциям. Разберёмся с ситуацией на примере.
Ярлыки:
программирование,
python
Подписаться на:
Комментарии к сообщению (Atom)
Спасибо, я тоже из С++ пришвартовался даже перешел по запросу "перегрузка вычитания в python"
ОтветитьУдалитьСпасибо наконец-то уяснил про перегрузку, а то везде как-то пишут запутано, а тут понятно.
ОтветитьУдалить