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

如何为Pydantic BaseModel子类私有属性实现带验证的自定义__init__

Pydantic BaseModel私有属性在自定义__init__中的问题解决

问题描述

创建带有自定义__init__方法的Pydantic BaseModel子类时,尝试通过super().__init__(**kwargs)传递下划线前缀的私有属性(如_a、_b),执行时触发AttributeError: 'MyClass' object has no attribute '_a'异常,但将私有属性改为非下划线前缀后运行正常。需要保留现有结构同时使用私有属性。

示例代码

from pydantic import BaseModel, ValidationError, model_validator

c2b = {
    "work week": 1,
    "weekend": 2,
}


class MyClass(BaseModel):

    _a: int
    _b: int

    @model_validator(mode="after")
    def validator(self) -> None:

        if self._a <= 0:
            raise ValidationError("a must be positive.")

    def __init__(self, a: int, c: str) -> None:

        super().__init__(
            _a=a,
            _b=c2b[c],
        )

MyClass(1, "weekend")

原因分析

Pydantic默认将以下划线开头的字段归为受保护命名空间(默认protected_namespaces包含('model_', '_')),不会把这些字段纳入模型的字段系统。因此调用super().__init__()时传入的_a、_b不会被处理并设置到实例上,导致验证器无法访问这些属性。

解决方案

方案1:使用PrivateAttr显式声明私有属性

通过PrivateAttr()标记私有属性,让Pydantic将其识别为实例私有属性,直接在自定义__init__中赋值:

from pydantic import BaseModel, ValidationError, model_validator, PrivateAttr

c2b = {
    "work week": 1,
    "weekend": 2,
}


class MyClass(BaseModel):
    _a: int = PrivateAttr()
    _b: int = PrivateAttr()

    @model_validator(mode="after")
    def validator(self) -> None:
        if self._a <= 0:
            raise ValidationError("a must be positive.")

    def __init__(self, a: int, c: str) -> None:
        # 直接为私有属性赋值
        self._a = a
        self._b = c2b[c]
        # 调用父类初始化,无需传递私有属性参数
        super().__init__()

MyClass(1, "weekend")

方案2:修改模型配置,允许下划线开头的字段作为普通模型字段

通过model_config将protected_namespaces设置为空元组,取消下划线开头字段的保护限制:

from pydantic import BaseModel, ValidationError, model_validator

c2b = {
    "work week": 1,
    "weekend": 2,
}


class MyClass(BaseModel):
    _a: int
    _b: int

    # 取消下划线开头字段的保护限制
    model_config = {"protected_namespaces": ()}

    @model_validator(mode="after")
    def validator(self) -> None:
        if self._a <= 0:
            raise ValidationError("a must be positive.")

    def __init__(self, a: int, c: str) -> None:
        super().__init__(
            _a=a,
            _b=c2b[c],
        )

MyClass(1, "weekend")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 17:04:50