You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为继承父类验证器的attrs子类设置属性默认值?

attrs子类设置父类字段默认值并保留验证器的正确方式

首先看给定的父类定义:

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")

需求很明确:创建Car、Motorbike这类子类,给num_wheels设置专属默认值(比如Car默认4轮,Motorbike默认2轮),同时要保留父类的验证逻辑——既不能让非法值(比如负数、非整数)通过初始化,又要支持无参调用Car()或Motorbike()自动使用默认值。

你提到的手动实现__init__调用__attrs_init__的方案是可行的:

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

这个写法能正常触发父类的所有验证器,因为__attrs_init__是attrs自动生成的初始化方法,会完整执行父类定义的字段校验逻辑。但这种写法不够简洁,attrs本身提供了更优雅的实现方式。

更合适的实现方式

直接在子类中重新声明num_wheels字段,指定默认值的同时复用父类的验证器:

@define(kw_only=True)
class Car(Vehicle):
    num_wheels: int = field(
        default=4,
        validator=Vehicle.num_wheels.validator
    )

@define(kw_only=True)
class Motorbike(Vehicle):
    num_wheels: int = field(
        default=2,
        validator=Vehicle.num_wheels.validator
    )

这样写既保留了父类的双重验证(类型检查+正整数校验),又给子类设置了专属默认值,而且完全符合attrs的语法规范。

如果觉得每次引用Vehicle.num_wheels.validator有点繁琐,还可以把父类的验证器抽成独立函数,这样子类直接复用更方便:

from attrs import define, field, validators

def validate_positive_int(attribute, value) -> None:
    if not isinstance(value, int):
        raise TypeError(f"{attribute.name} must be an integer")
    if value <= 0:
        raise ValueError(f"{attribute.name} must be greater than 0")

@define(kw_only=True)
class Vehicle:
    num_wheels: int = field(validator=validate_positive_int)

@define(kw_only=True)
class Car(Vehicle):
    num_wheels: int = field(default=4, validator=validate_positive_int)

@define(kw_only=True)
class Motorbike(Vehicle):
    num_wheels: int = field(default=2, validator=validate_positive_int)

这种方式进一步解耦了验证逻辑,代码复用性更强,后续如果要修改验证规则,只需要修改validate_positive_int一个函数即可。

验证效果测试

不管用哪种方式,以下测试场景都能符合预期:

  • Car():正常初始化,num_wheels为4
  • Motorbike(num_wheels=3):正常初始化
  • Car(num_wheels=-1):抛出ValueError
  • Car(num_wheels=3.14):抛出TypeError(或ValueError,取决于验证器顺序)

内容的提问来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 06:03:10