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

引入Pydantic后标准库frozen+slots数据类报只读属性错误原因?

标准库数据类结合Pydantic后初始化报错问题

首先看一段可正常运行的标准库数据类代码:

from dataclasses import dataclass

@dataclass(slots=True, frozen=True)
class MyStdLibDataclass:
    x : int = 0

d1 = MyStdLibDataclass(x=100)
assert d1.x == 100

但在同一文件中添加Pydantic相关代码后:

from pydantic import BaseModel

class MyModel(BaseModel):
    y : MyStdLibDataclass|None = None

d2 = MyStdLibDataclass(x=101) # 此处报错
assert d2.x == 101

会触发以下错误:

Traceback (most recent call last):
  File "C:\Users\Ross\Desktop\dataclass_bug.py", line 15, in <module>
    d2 = MyStdLibDataclass(x=101)
  File "<string>", line 3, in __init__
AttributeError: 'MyStdLibDataclass' object attribute 'x' is read-only

问题原因

Pydantic 2.x在处理标准库数据类时,会对数据类进行运行时动态增强,添加验证相关逻辑。但对于同时设置了slots=True和frozen=True的数据类,这个增强过程会干扰原有的初始化逻辑,导致第一次赋值时错误地判定字段为只读状态。

Pydantic并没有修改标准库数据类的核心实现,但动态增强的过程和frozen=True+slots=True的组合存在兼容性冲突。

解决方案

有几种可行的解决方式:

  • 调整数据类参数:移除slots=True或frozen=True中的一个。比如只保留只读特性:
@dataclass(frozen=True)
class MyStdLibDataclass:
    x : int = 0

或只保留内存优化的slots特性:

@dataclass(slots=True)
class MyStdLibDataclass:
    x : int = 0
  • 使用Pydantic数据类替代标准库版本:Pydantic的dataclass原生支持slots=True和frozen=True的组合,不会出现兼容问题:
from pydantic.dataclasses import dataclass

@dataclass(slots=True, frozen=True)
class MyStdLibDataclass:
    x : int = 0
  • 阻止Pydantic增强标准库数据类:通过Annotated搭配PlainSerializer,让Pydantic直接使用原始数据类,不做额外修改:
from pydantic import BaseModel, PlainSerializer
from typing import Annotated

class MyModel(BaseModel):
    y: Annotated[MyStdLibDataclass|None, PlainSerializer(lambda x: x)] = None

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 07:47:53