如何为使用父类验证器的attrs子类设置默认值?

0 投票
1 回答
35 浏览
提问于 2025-04-14 16:17

考虑这个简单的例子:

from attrs import define, field, validators

@define(kw_only=True)
class Vehicle:
    num_wheels: int = field(validator=validators.instance_of(int))

    @num_wheels.validator
    def validate_num_wheels(self, attribute, value) -> None:
        if value <= 0:
            raise ValueError("Number of wheels must be greater than 0")

我该如何创建这个父类的子类,让它们可以设置自己的默认值,比如 num_wheels 的值,同时还能运行父类里定义的验证器呢?举个例子:

@define
class Car(Vehicle):
    # num_wheels: int = 4  #! this doesn't work
    pass


@define
class Motorbike(Vehicle):
    # num_wheels: int = 2
    pass

我想要防止出现 Car(num_wheels=3.14)Car(num_wheels=-1) 这样的情况。但我也希望 Car()Motorbike() 能够使用默认值进行初始化。

我看到过一个可能相关的回答 - https://stackoverflow.com/a/67129088/11432894。它建议这可能是一个解决方案?

@define
class Car(Vehicle):
    def __init__(self, *, num_wheels: int = 4, **kwargs):
        self.__attrs_init__(num_wheels=num_wheels, **kwargs)

1 个回答

1

看起来你想要重复使用字段定义,但这目前是个未解决的问题:https://github.com/python-attrs/attrs/issues/637

在评论中提到的,轮子的数量应该是类的一部分,而不是一个属性。我想你也可以把你的车辆类设为“抽象”,然后写一个验证器,这个验证器会从类中读取这个属性(也就是说,它会检查self.num_wheels,而num_wheels是一个ClassVar)。

撰写回答