如何输入检查 class 属性

How to input-check a class property

我有一个 class MyClass 具有 class 属性 SOMETHING:

class MyClass(object):
    SOMETHING = 12

我希望 SOMETHING 被强制执行以满足特定条件,例如SOMETHING < 100。 我该怎么做?

最终,此 class 应由用户 class 编辑,例如:

class MySubClass(MyClass):
    SOMETHING = 13

我一直在研究 class-属性 概述的方法 here,但它们似乎都不能很好地定义class 正文中的 属性。

例如:

class MyClassMeta(type):
    _SOMETHING = 0

    @property
    def SOMETHING(cls):
        return cls._SOMETHING

    @SOMETHING.setter
    def SOMETHING(cls, something):
        if something < 100:
            cls._SOMETHING = something
        else:
            raise ValueError('SOMETHING must be < 100')


class MyClass(object, metaclass=MyClassMeta):
    # this is ignored
    SOMETHING = 100


x = MyClass()
print(MyClass.SOMETHING)
# 0
print(type(x).SOMETHING)
# 0

但是,如果正常访问该属性,例如:

MyClass.SOMETHING = 50
print(MyClass.SOMETHING)
# 50
print(type(x).SOMETHING)
# 50

它工作正常,即使使用 subclassing:

class MySubClass(MyClass):
    SOMETHING = 40


y = MySubClass()
print(MySubClass.SOMETHING)
# 50
print(type(y).SOMETHING)
# 50

除了subclass中的设置SOMETHING也会被忽略。

那么,当 class 的正文中定义了 SOMETHING 时,如何触发 @SOMETHING.setter 代码的执行?

首先。使用两个下划线来保存从外部访问的属性。 第二:如果您从基础 class 继承,则 属性 仍然可用。不需要重新定义它。

使用以下简单的 metaclass 实现来验证 class 声明阶段的特定属性:

class MyClassMeta(type):
    def __new__(cls, clsname, bases, clsdict):
        if clsdict['SOMETHING'] >= 100:  # validate specific attribute value
            raise ValueError(f'{clsname}.SOMETHING should be less than 100')
        return type.__new__(cls, clsname, bases, clsdict)


class MyClass(metaclass=MyClassMeta):
    SOMETHING = 12


class MyChildClass(MyClass):
    SOMETHING = 100

运行 抛出:

ValueError: MyChildClass.SOMETHING should be less than 100

https://docs.python.org/3/reference/datamodel.html#basic-customization