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

如何使用attrs验证Literal类型或None的实例?

规范解决方案:用attrs内置验证器处理Literal|None类型验证

原代码的核心问题是instance_of验证器仅支持运行时存在的类/类型,而Literal是静态类型提示,不属于运行时可实例化的类,因此直接传入Literal[OK_ARGS]会触发Subscripted generics cannot be used with class and instance checks错误。同时注意:类装饰器应该用@frozen或@define而非@field,原代码存在装饰器误用问题。

以下是两种规范的实现方式:


方式一:结合optional与in_内置验证器(推荐)

Literal['a','b']的本质是限制值必须在指定列表内,因此直接用in_验证器检查值范围,再用optional处理None的情况,完全匹配Literal|None的类型约束:

from attrs import frozen, field
from attrs.validators import optional, in_
from typing import Literal

OK_ARGS = ['a', 'b']

@frozen
class MyClass:
    my_field: Literal['a', 'b'] | None = field(validator=optional(in_(OK_ARGS)))
  • optional验证器会自动跳过None值的检查;
  • 当值非None时,in_(OK_ARGS)会验证值是否在允许的列表中,错误提示符合attrs的标准格式。

方式二:从Literal类型中自动提取允许值

如果希望验证逻辑与类型提示完全绑定(修改Literal时无需手动同步OK_ARGS),可以用typing.get_args提取Literal的参数:

from attrs import frozen, field
from attrs.validators import optional, in_
from typing import Literal, get_args

@frozen
class MyClass:
    # 定义Literal类型
    MyFieldType = Literal['a', 'b'] | None
    my_field: MyFieldType = field(
        # 从Literal中提取允许的非None值
        validator=optional(in_(get_args(Literal['a', 'b']))),
    )

或者将允许值提前提取,让代码更清晰:

ALLOWED_VALUES = get_args(Literal['a', 'b'])

@frozen
class MyClass:
    my_field: Literal['a', 'b'] | None = field(validator=optional(in_(ALLOWED_VALUES)))

对比自定义验证器的优势

  • 复用attrs内置验证器,代码更简洁、可读性更强;
  • 错误提示标准化(attrs内置验证器会输出统一格式的错误信息);
  • 无需手动编写类型检查逻辑,降低维护成本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:51:56