简体   繁体   English

python-attrs:子类中的验证器

[英]python-attrs: validator in child class

Using the Python module attrs, I'm trying to have a subclass with a condition on its attributes more restrictive than its parent, like in the minimal example below. 使用Python模块attrs,我正在尝试创建一个子类,其子类的条件要比其父类具有更严格的条件,如下面的最小示例所示。

import attr

@attr.s
class Base:
    x = attr.ib()
    y = attr.ib()

@attr.s
class Child(Base):

    @x.validator
    def _x_validator(self, a, x):
        if x < 0:
            raise ValueError()

Defining a validator like above raises an error ( NameError: name 'x' is not defined ). 像上面定义验证器会引发错误( NameError: name 'x' is not defined )。

I've found a workaround by redefining x in the child class. 我通过在子类中重新定义x找到了一种解决方法。

@attr.s
class Child(Base):
    x = attr.ib()

    @x.validator
    def _x_validator(self, a, x):
        if x < 0:
            raise ValueError()

However it messes up the ordering of the attributes. 但是,它弄乱了属性的顺序。

In [5]: Child(5, 10)
Out[5]: Child(y=5, x=10)

So, finally, I ended up redefining all the attributes in the child class (and there are more than two in the actual code). 因此,最后,我最终重新定义了子类中的所有属性(实际代码中有两个以上)。

Is there a more elegant way to do this? 有没有更优雅的方法可以做到这一点?

Finally, the simplest workaround I found was simply not to use a validator in the child class: 最后,我发现的最简单的解决方法就是在子类中不使用验证器:

@attr.s
class Child(Base):
    def __attrs_post_init__(self):
        assert self.x > 0

Thanks to bruno desthuilliers for rightly pointing out Liskov principle. 感谢bruno desthuilliers正确指出了Liskov原则。 Note that the problem does not only occur for @x.validator but also for other constructs such as the attribute default value @x.default . 注意,不仅对于@x.validator还会发生此问题,对于其他构造(例如属性默认值@x.default也不会出现此问题。 It seems that the upcoming dataclass for Python 3.7 works slightly better with inheritance than attrs in this case. 在这种情况下,似乎即将发布的Python 3.7 dataclass继承方面的工作要比attrs 更好

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM