Automatic class assignment (or validation) on output


I have a base class from which I get several subclasses.
Each subclass defines class constants, and I want to apply certain restrictions to them. For instance:

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 

I want to be able to apply the rule (NOM% DENOM == 0).
I am currently doing this with a class decorator:

 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 

But I do not like the fact that I need to decorate each subclass (I have a lot). I am wondering if this can be done directly with some manipulations in the base class.

Any tips?

+4
source share
2 answers

Good, funny. I thought about this for a while, but only after the publication of the question - especially when choosing tags and adding a "metaclass" - I realized that I could answer myself. So, presented for review and future knowledge, it says here:

 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 anymore... NOMINATOR = 1 DENOMINATOR = 1 

And now all the children should be automatic.

+8
source

You can check in the constructor of base classes

 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) 

When you create an instance of Subclass_bad() , you will get an AssertionError .

+1
source

Source: https://habr.com/ru/post/1332761/


All Articles