Множественная диспетчеризация Foo и Bar
x_with_y = Dispatch([((object, object), <<exception block>
>
)]) x_with_y.add_rule((Foo,Foo), <<FooFoo block>
>
) x_with_y.add_rule((Foo,Bar), <<FooBar block>
>
) x_with_y.add_rule((Bar,Foo), <<BarFoo block>
>
) x_with_y.add_rule((Bar,Bar), <<BarBar block>
>
) #...call the function x_with_y() using some arguments... x_with_y(something, otherthing)
Я думаю, что эта симметричность полиморфной диспетчеризации по множеству аргументов гораздо более элегантна, чем предшествующий стиль. Кроме того, этот стиль позволяет документировать одинаковую роль этих двух объектов, задействованных в определении подходящей ветви кода.
Стандартный Python не разрешает конфигурировать этот тип множественной диспетчеризации; но, к счастью, вы можете сделать это, воспользовавшись написанным мною модулем multimethods. См. , чтобы скачать этот модуль отдельно или в составе утилит Gnosis. После того, как вы установили multimethods, все, что от вас требуется - включить в начало своего приложения следующую строку:
from multimethods import Dispatch
"Мультиметоды", как правило, это синоним множественной диспетчеризации; но термин мультиметод предполагает конкретную функциональную/объектную реализацию более абстрактной концепции множественной диспетчеризации.
Экземпляр Dispatch - это вызываемый объект, его можно конфигурировать с любым желаемым количеством правил. К тому же, можно использовать метод Dispatch.remove_rule(), чтобы удалять правила; благодаря этому множественная диспетчеризация с использованием multimethods становится несколько более динамичной, чем статическая иерархия классов (но вы также можете совершить некие замысловатые действия с классами Python во время исполнения). Также заметьте, экземпляр Dispatch может принимать переменное число аргументов; сопоставление выполняется сначала по числу аргументов, затем по их типам. Если экземпляр Dispatch вызывается с любым шаблоном, который не определен в правиле, возбуждается TypeError. Инициализация x_with_y() с запасным шаблоном (object,object) необязательна, если вы просто хотите, чтобы в неопределенных ситуациях возбуждалось исключение.
Каждый кортеж (pattern,function), перечисленный в инициализации Dispatch, просто передается далее в метод .add_rule();
это исключительно вопрос удобства программирования - устанавливать правила при инициализации или позже (можно комбинировать подходы, как в предшествующем примере). При вызове функции из диспетчера аргументы, используемые при вызове, передаются диспетчеру; вы должны обеспечить, чтобы функция, которую вы используете, могла принять то число аргументом, с которым она сопоставляется. Например, приведенные ниже вызовы эквиваленты: