0

假设我们有一个attrs类:

@attr.s()
class Foo:
    a: bool = attr.ib(default=False)
    b: int = attr.ib(default=5)
    
    @b.validator
    def _check_b(self, attribute, value):
        if not self.a:
            raise ValueError("to define 'b', 'a' must be True")
        if value < 0:
            raise ValueError("'b' has to be a positive integer")

所以以下行为是正确的:

>>> Foo(a=True, b=10)
Foo(a=True, b=10)

>>> Foo(b=10)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<attrs generated init __main__.Foo>", line 5, in __init__
    __attr_validator_b(self, __attr_b, self.b)
  File "<input>", line 9, in _check_b
ValueError: to define 'b', 'a' must be True

但这不是:

>>> Foo()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<attrs generated init __main__.Foo>", line 5, in __init__
    __attr_validator_b(self, __attr_b, self.b)
  File "<input>", line 9, in _check_b
ValueError: to define 'b', 'a' must be True

这显然会发生,因为Foo.b无论何时Foo.a给定值,总是被初始化:通过默认值或 on Foo.__init__

无论如何,是否可以使用任何初始化挂钩来完成此属性依赖?

4

2 回答 2

1

遵循@hynek 的建议,即使用导致有效实例的默认值,我已将default依赖属性更改None为仅在传递值时进行验证__init__

@attr.s()
class Foo:
    a: bool = attr.ib(default=False)
    b: Optional[int] = attr.ib(default=None)
    
    @b.validator
    def _check_b(self, attribute, value):
        if value is None:
            self.b = 5
            return
        if not self.a:
            raise ValueError("to define 'b', 'a' must be True")
        if value < 0:
            raise ValueError("'b' has to be a positive integer")

我知道在验证器上更改属性值并不是最优的,但它可以完成工作。

关于验证器的文档可以在这里找到

于 2021-08-05T11:42:32.207 回答
0

根据您想要做什么,您可以检查是否value是默认值(在 上可用attribute.default)。但是,您的整个问题是,根据您的验证器,默认值会导致一个实例无效。因此,可能有更好的方法来对此进行建模。

于 2021-08-05T06:21:38.907 回答