[英]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.