Хороший способ организовать все подклассы в словарь на python?

#python #regex

#python #регулярное выражение

Вопрос:

У меня есть базовый класс и несколько подклассов. Каждый подкласс имеет атрибут с именем «регулярное выражение», содержащий строку:

 # module level dictionary
action_types = {}

class Action():
    regex = '.*'

    @classmethod
    def register_action(cls):
        action_types[cls.regex] = cls


class Sing(Action):
    regex = r'^SING [0-9] '
    Sing.register_action()

class Dance(Action):
    regex = r'^DANCE [0-9] '
    Dance.register_action()
  

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

Приведенный выше пример не работает, и я полагаю, это связано с тем, что переменные Dance и Sing еще недоступны в пространстве имен, когда они используются.

Есть ли какой-либо способ зарегистрировать подклассы в словаре во время инициализации класса?

Комментарии:

1. Почему вы используете для этого отдельные классы? Что плохого в том, чтобы сделать регулярное выражение членом экземпляра и экземплярами Sing, Dance и т. Д.?

2. На практике я хочу, чтобы классы Sing и Dance имели уникальные функции инициализации . Я думаю, что использование шаблона метакласса, как в примере, представленном Игнасио, на самом деле обеспечивает лучшее из обоих миров — подклассы являются экземплярами, но также могут иметь уникальные функции инициализации.

Ответ №1:

Это не то, как вы хотите это сделать.

 class ActionRegistry(type):
  registry = {}
  def __init__(cls, name, bases, dic):
    if 'regex' in dic:
      cls.registry[dic['regex']] = cls
    super(ActionRegistry, cls).__init__(name, bases, dic)

class Action(object):
  __metaclass__ = ActionRegistry

class Sing(Action):
  regex = r'^SING [0-9] '

class Dance(Action):
  regex = r'^DANCE [0-9] '
  

Ответ №2:

Это работает:

 action_types = {}

class Action():
    regex = '.*'

    @classmethod
    def register_action(cls):
        action_types[cls.regex] = cls


class Sing(Action):
    regex = r'^SING [0-9] '
Sing.register_action()

class Dance(Action):
    regex = r'^DANCE [0-9] '
Dance.register_action()
  

Ответ №3:

Не пытайтесь делать это во время инициализации класса.

Вот более простой способ сделать это:

 action_types = {}

class Action():
    regex = '.*'

class Sing(Action):
    regex = r'^SING [0-9] '

class Dance(Action):
    regex = r'^DANCE [0-9] '

def register_action(cls):
    action_types[cls.regex] = cls

for cls in (Sing, Dance):
    register_action(cls)