Автоматическое присвоение класса (или проверка) при выводе

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

class Base(object): # define these in your sub-class, and make sure (NOM % DENOM == 0) NOMINATOR = None DENOMINATOR = None class Subclass_good(Base): NOMINATOR = 6 DENOMINATOR = 3 class Subclass_bad(Base): NOMINATOR = 7 DENOMINATOR = 5 

Я хочу, чтобы иметь возможность применять правило (NOM% DENOM == 0).
В настоящее время я делаю это с помощью декоратора класса:

 def nom_denom_validator(cls): assert(cls.NOMINATOR % cls.DENOMINATOR == 0) return cls # and decorate each subclass, eg: @nom_denom_validator class Subclass_another(Base): NOMINATOR = 9 DENOMINATOR = 12 

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

Любой совет?

Хорошо, смешно. Я думал об этом некоторое время, но только после публикации вопроса – особенно при выборе тегов и добавлении «метакласса» – я понял, что могу ответить сам.
Итак, представленный для обзора и будущих знаний, здесь говорится:

 class Base_Metaclass(type): def __new__(meta, classname, bases, class_dict): new_type = type.__new__(meta, classname, bases, class_dict) if not (new_type.NOMINATOR % new_type.DENOMINATOR) == 0: raise Exception("Invalid subclass created - validation failed") return new_type # have Base and all its descendants be enforced: class Base(object): __metaclass__ = Base_Metaclass # I must pass the validation myself, no None's anymore... NOMINATOR = 1 DENOMINATOR = 1 

И теперь все дети должны быть автоматическими.

Вы можете выполнить проверку в конструкторе базовых классов

 class Base(object): # define these in your sub-class, and make sure (NOM % DENOM == 0) NOMINATOR = None DENOMINATOR = None def __init__(self): assert(self.NOMINATOR % self.DENOMINATOR == 0) 

Когда вы создаете экземпляр Subclass_bad() , вы получите AssertionError .