派生时的自动类装饰(或验证)
Posted
技术标签:
【中文标题】派生时的自动类装饰(或验证)【英文标题】:Automatic class decoration (or validation) upon derivation 【发布时间】:2011-05-28 06:21:18 【问题描述】:我有一个基类,从中派生出多个子类。 每个子类都定义了类常量,我希望对它们实施某些限制。 例如:
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, e.g.:
@nom_denom_validator
class Subclass_another(Base):
NOMINATOR = 9
DENOMINATOR = 12
但我不喜欢我需要装饰每个子类的事实(我有很多)。我很感兴趣这是否可以通过直接对 Base 类进行一些操作来完成。
有什么建议吗?
【问题讨论】:
【参考方案1】:好吧,有趣。我考虑了一段时间,但只有在发布问题之后 - 特别是在选择标签并在那里添加“元类”时 - 我才意识到我自己可能有一个答案。 所以,提交审查和未来的知识,这里是:
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
现在所有的孩子都应该被自动强制执行。
【讨论】:
是的,如果你想继承类级别的行为,你需要一个元类。如果你不想继承它,你需要一个类装饰器。【参考方案2】:您可以在基类构造函数中进行检查
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
。
【讨论】:
这确实可以防止坏实例,但我希望防止“在编译时”创建无效的子类本身。 你不能在编译时这样做:编译时是你将捕获语法错误的时间,但元类解决方案将检查何时在运行时定义类,或检查基类类构造函数将检查实例何时创建,也在运行时。 @Duncan:你是对的,当然。我指的是导入时的类对象定义,那肯定是在运行时。以上是关于派生时的自动类装饰(或验证)的主要内容,如果未能解决你的问题,请参考以下文章