Использование getattr (…) для поиска обработчиков событий с использованием сконструированных имен

В телефонной индустрии я много работаю с системами событий и часто заканчиваю тем, что пишу много операторов if, чтобы помочь создать своего рода дерево решений. Часто я хочу знать только о первом или втором произошедшем событии. Например, индикатор звонка или при первом вызове распознается голос. Написание большого и сложного дерева if или каскадных операторов if вместе может привести к нежелательным сбоям и царапинам в голове позже.

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

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

То, что мы видим выше, является простым примером, когда мы хотим знать, какой еды обезьяны голодны и бросают ли они что-нибудь. Нас не волнует то, что они бросают, а заботит только то, что они бросают.

Функция dispatch_event содержит логику того, как мы хотим отправлять события. Мы должны явно вызывать функции по имени, что дает нам возможность называть функцию любым, черт возьми, хорошо выбранным нами. По мере того, как сложность нашей программы растет, и мы хотим начать добавлять дополнительные функции или ограничивать обработку событий на основе других параметров или предыдущих событий, наш сценарий действительно станет очень сложным.

На этом этапе мне бы очень хотелось знать, когда какая-либо из обезьян голодна по банану, и я хочу обработать это событие только один раз. Обезьяны любят бананы, но их нельзя перекармливать!

Сладко!… Мы использовали новый Счетчик для каждой обезьяны и ключ, составленный из данных событий, чтобы помочь нам передать новое значение, называемое _count, нашим функциям обработчика событий. Оттуда мы можем попытаться определить, являемся ли мы первым событием этого типа для каждой обезьяны, где это применимо.

Эта event_type переменная выглядит весьма полезной для других целей ... не так ли! Пора стать динамичным!

Перепишите время. Мы должны действительно использовать, насколько хороша эта переменная event_type, и попытаться упростить функцию dispatch_events. Я обнаружил, что присвоение имен функциям на основе их ... ну ... функции действительно очень полезно, и нет никаких причин, по которым это не может соответствовать какой-либо квалификации ранее.

Теперь код использует getattr против модуля __main__ (глобальный уровень), чтобы найти потенциальное совпадение на основе приоритета совпадения. В этом случае чем длиннее, тем лучше.

Поскольку мы определили do_monkey_hungry_banana_1, но не do_monkey_hungry_banana, мы обязательно дадим обезьяне только один банан.

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

Ради интереса давайте воспользуемся модулем inflect, чтобы немного очистить его. Используя inflect, мы можем превратить event_count из 1 или 2 в first и second. Ниже добавлен движок inflect и переименован do_monkey_hungry_banana_1 в do_monkey_hungry_banana_first, а также добавлен do_monkey_hungry_banana_second (о нет!).

Я очень надеюсь, что вы многое узнали из этой статьи! На первый взгляд эта техника может показаться немного глупой, но она сэкономила мне кучу времени и избавила меня от волос в ходе некоторых грандиозных проектов.

Если у вас есть что добавить, пожалуйста, сообщите мне!