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

继承内置list的Pydantic自定义类型实例化类型异常问题

解决Pydantic自定义List子类实例被转为普通list的问题

问题根源

Pydantic对list、dict这类序列类型有默认解析逻辑:无论输入是内置类型还是其子类实例,都会被自动转换为对应的内置类型。哪怕你的validate方法被触发且输入是ListSubclass,后续处理步骤仍会把它转成普通list。

可行解决方案

1. 在validate方法中强制返回自定义子类实例

修改validate方法,确保无论输入是什么类型,最终都返回ListSubclass实例:

from pydantic import BaseModel

class ListSubclass(list):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        # 先校验输入合法性
        if not isinstance(v, (list, cls)):
            raise ValueError("输入必须是列表或ListSubclass实例")
        # 显式返回ListSubclass实例,覆盖Pydantic的默认转换
        return cls(v)

class TestModel(BaseModel):
    test_field: ListSubclass = ListSubclass([1,2,3])

# 验证效果
obj_default = TestModel()
print(type(obj_default.test_field))  # <class '__main__.ListSubclass'>

obj_custom = TestModel(test_field=ListSubclass([4,5,6]))
print(type(obj_custom.test_field))  # <class '__main__.ListSubclass'>

2. Pydantic v2 专用:用PlainSerializer跳过默认转换

如果使用Pydantic v2,可通过PlainSerializer直接保留自定义子类实例,无需修改validate逻辑:

from pydantic import BaseModel, PlainSerializer, WithJsonSchema
from typing import Annotated

class ListSubclass(list):
    pass

# 用Annotated包装自定义类型,指定序列化规则
CustomList = Annotated[
    ListSubclass,
    PlainSerializer(lambda x: x, return_type=list),
    WithJsonSchema({"type": "array", "items": {"type": "integer"}})
]

class TestModel(BaseModel):
    test_field: CustomList = ListSubclass([1,2,3])

obj = TestModel(test_field=ListSubclass([4,5,6]))
print(type(obj.test_field))  # <class '__main__.ListSubclass'>

核心提示

  • 继承内置序列类型时,Pydantic的默认行为是标准化为内置类型,必须显式指定返回自定义实例才能保留类型
  • Pydantic v1依赖validate方法的返回值控制类型;v2可借助序列化器更灵活处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 00:12:47