【发布时间】:2018-07-25 02:11:01
【问题描述】:
使用 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)
所以,最后,我最终重新定义了子类中的所有属性(实际代码中不止两个)。
有没有更优雅的方法来做到这一点?
【问题讨论】:
-
我没有使用
python-attrs的经验(恕我直言,这是一个典型的“不是一个好主意”,即往往会产生比它解决的问题更多的问题,并使代码比它必须的更复杂),但无论如何:你试过@Base.x.validator吗?请注意,我实际上不认为它会按预期工作(我怀疑它会将验证器应用于Base.x,因此应用于Base及其所有子类)。 -
另外请注意,向子类添加限制会破坏 Liskov 的替换原则 (en.wikipedia.org/wiki/Liskov_substitution_principle),因此您的子类不再是其父类的正确子类型。在子类型化不需要继承的 Python 中,这不一定是个问题,但我想我最好提一下,因为它可能会揭示设计问题。
标签: python python-attrs