Регистрация обработчиков для класса - PullRequest
1 голос
/ 19 июня 2011

Я пытаюсь найти хороший способ легко зарегистрировать обработчики некоторых команд в классе 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 на мета-класс.Он также может связывать обработчики во время создания класса.Но это кажется еще более сложным, чем нынешний подход.

Есть ли какой-нибудь более легкий выход?

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

@register_handlers
class SubClass(SomeBaseClass):
    @actual_handler_wrapper
    def handler(self):
       ...

1 Ответ

2 голосов
/ 19 июня 2011

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

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, но я полагаю, что это зависит откак это будет называться и каковы ваши личные предпочтения.

...