开发者

Automatic class decoration (or validation) upon derivation

I have a base class from which I derive multiple subcl开发者_开发知识库asses.

Each subclass defines class constants, and I wish to enforce certain limitations on them. For example:

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 enforce the rule (NOM % DENOM == 0).

I currently do this with a class decorator:

def nom_denom_validator(cls):
    assert(cls.NOMINATOR % cls.DENOMINATOR == 0)
    return cls

# and decorate each subclass, e.g.:
@nom_denom_validator
class Subclass_another(Base):
    NOMINATOR = 9
    DENOMINATOR = 12

But I don't like the fact that I need to decorate each subclass (I have plenty). I'm interested whether this can be done by some manipulation on the Base class directly.

Any advice?


Ok, funny. I was thinking about it for a while, but only after posting the question - specifically when choosing tags, and adding "metaclass" there - did I realize I may have an answer myself.
So, submitted for review and future knowledge, here goes:

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

And now all children should be auto-enforced.


You can do the checking in the base classes constructor

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'll get AssertionError.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜