使用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()像上面这样定义一个验证器会引发一个错误(NameError: name 'x' is not defined)。
通过在子类中重新定义x,我找到了一个解决办法。
@attr.s
class Child(Base):
x = attr.ib()
@x.validator
def _x_validator(self, a, x):
if x < 0:
raise ValueError()然而,它扰乱了属性的排序。
In [5]: Child(5, 10)
Out[5]: Child(y=5, x=10)最后,我重新定义了子类中的所有属性(实际代码中有两个以上)。
有什么更优雅的方法吗?
发布于 2018-03-12 10:40:50
最后,我发现最简单的解决方法就是在子类中不使用验证器:
@attr.s
class Child(Base):
def __attrs_post_init__(self):
assert self.x > 0感谢布鲁诺·德斯特利勒正确地指出了李斯科夫的原则。请注意,这个问题不仅发生在@x.validator上,而且也发生在其他构造上,比如属性默认值@x.default。在这种情况下,即将推出的Python3.7继承的效果稍好一些的dataclass似乎要比attrs的要好。
https://stackoverflow.com/questions/48788285
复制相似问题