Автоматическое воспроизведение диспетчеризации
class General(object): pass class Between(General): pass class Specific(Between): pass dispatch = Dispatch() dispatch.add_rule((General,), lambda _:"Gen", AT_END) dispatch.add_rule((Between,), lambda _:"Betw", AT_END) dispatch.add_rule((Specific,), lambda _:"Specif", AT_END) dispatch(General()) # Result: ['Gen'] dispatch(Specific()) # Result: ['Specif', 'Betw', 'Gen']
Разумеется, в некоторых ситуациях (как для правила (General)) менее специфичное правило отсутствует. Для обеспечения единообразия, однако, каждое обращение к диспетчеру возвращает список значений из всех функций, которым передается управление таким образом. Если в правиле не определены ни AT_END, ни AT_START, распространение вызовов не производится (и возвращается список из одного элемента). Этим объясняется индекс [0] в примере с фигурами, который, вероятно, кажется загадочным .
Для тонкой настройки распространения вызовов применяется метод диспетчера .next_method(). Чтобы задать распространение вызовов вручную, нужно использовать для определения правил метод .add_dispatchable(), а не метод .add_rule(). Кроме того, диспетчеризованные функции сами должны принимать аргумент dispatch. При вызове диспетчера вы либо должны передать аргумент, задающий диспетчер, либо вы можете воспользоваться вспомогательным методом .with_dispatch(). Например: