Регистрация обработчиков для класса

1

Я пытаюсь найти хороший способ легко зарегистрировать обработчики некоторых команд в классе Python. Эти обработчики будут зарегистрированы для подклассов SomeBaseClass и доступны только там. К сожалению, я начинаю думать, что делаю больше работы, чем нужно. Прямо сейчас у меня есть:

def register_handlers(cls):
    cls._handlers = {}
    for method in cls.__dict__.values():
        if hasattr(method, "handler_name"):
            cls._handlers[method.handler_name] = method
    return cls

class SomeBaseClass(object):
    _handlers = None
    def __init__(self):
        for h in self._handlers:
            self._handlers[h] = types.MethodType(self._handlers[h], self, SomeBaseClass)
    def run_action(self, name, *args):
        return self._handlers[name](*args)

def actual_handler_wrapper(f):
    ....
    f.handler_name = name
    ....

Здесь есть несколько проблем:

  • должен быть оформлен как класс, так и обработчики.
  • Второй уровень подклассов нелегко доступен (_handlers должен быть назначен и проверен на каждом уровне наследования)
  • привязки обработчиков к классу во время инициализации кажутся грязными...

Есть ли способ улучшить это? Вероятно, я мог бы избавиться от register_handlers, изменив SomeBaseClass как класс meta-. Он также может связывать обработчики во время создания класса. Но это кажется еще более сложным, чем нынешний подход.

Есть ли более простой выход?

Изменить: Пример использования:

@register_handlers
class SubClass(SomeBaseClass):
    @actual_handler_wrapper
    def handler(self):
       ...
  • 0
    Какую модель вы абстрагируете, как это? Является ли целью написать handler = SomeBaseClass._registry[some_name] позже? Или что-то другое?
  • 0
    @register_handlers ли @register_handlers быть выше class SomeBaseClass(object) ? А что такое cn ?
Показать ещё 1 комментарий
Теги:
handler
decorator

1 ответ

2

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

class SomeBaseClass(object):
    def run_action(self, name, *args):
        getattr(self, name + '_handler')(*args)

class SubClass(SomeBaseClass):
    def foo_handler(self):
        # called on run_action('foo')

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

  • 0
    Правда, это может быть более простой способ решения проблемы. Однако мне все еще интересно, могу ли я как-то упростить подход «реестра» ...
  • 0
    @viraptor: Использование соглашения об именах и метакласса избавит от декораторов. Или уменьшите их до одного декоратора класса, если вы не хотите использовать метакласс. Тем не менее, он просто дублирует то, что Python уже делает для вас, зачем?
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню