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

Pydantic模型继承与子类列表的类型不兼容问题咨询

问题分析

继承Pydantic模型时,若用子类列表重写父类中定义为父类列表的字段,mypy会抛出类型不兼容错误,但单个子类类型重写父类类型却能通过检查。

错误示例(mypy报错)

from pydantic import BaseModel

class Name(BaseModel):
    data: str

class EnglishName(Name):
    data: str

class Animal(BaseModel):
    name: list[Name]

class AmericaAnimal(Animal):
    name: list[EnglishName]  # Incompatible types in assignment (expression has type "list[EnglishName]", base class "Animal" defined the type as "list[Name]")

对比示例(通过检查)

from pydantic import BaseModel

class Name(BaseModel):
    data: str

class EnglishName(Name):
    data: str

class Animal(BaseModel):
    name: Name

class AmericaAnimal(Animal):
    name: EnglishName

错误原因

这是Python泛型的不变性导致的:

  • 单个类型(如Name和EnglishName)是协变的——子类类型可以安全替换父类类型,因此单个字段重写没问题。
  • 但list是不变泛型,list[EnglishName]和list[Name]被视为完全不兼容的类型。因为基类Animal的name字段理论上可以接受任意Name的子类实例(比如新增的ChineseName),但子类AmericaAnimal将字段限定为list[EnglishName]后,会破坏这个类型契约,mypy会阻止这种潜在不安全的写法。

解决方法

方法1:使用协变只读类型(Sequence)

如果字段仅需只读操作,改用Sequence[Name]替代list[Name]。Sequence是协变泛型,Sequence[EnglishName]可以安全兼容Sequence[Name]:

from typing import Sequence
from pydantic import BaseModel

class Name(BaseModel):
    data: str

class EnglishName(Name):
    data: str

class Animal(BaseModel):
    name: Sequence[Name]

class AmericaAnimal(Animal):
    name: Sequence[EnglishName]  # mypy检查通过

方法2:泛型Pydantic模型(推荐)

通过泛型基类让子类指定具体的列表元素类型,既保留类型安全,又支持可变操作:

from typing import Generic, TypeVar
from pydantic import BaseModel

# 定义绑定到Name的协变类型变量
T = TypeVar('T', bound='Name', covariant=True)

class Name(BaseModel):
    data: str

class EnglishName(Name):
    data: str

class Animal(BaseModel, Generic[T]):
    name: list[T]

# 子类指定具体类型,无需重写字段
class AmericaAnimal(Animal[EnglishName]):
    pass

方法3:临时绕过检查(不推荐)

如果需要快速绕过mypy检查,可结合override装饰器和类型忽略,但会失去类型校验保障:

from typing import override
from pydantic import BaseModel

class Name(BaseModel):
    data: str

class EnglishName(Name):
    data: str

class Animal(BaseModel):
    name: list[Name]

class AmericaAnimal(Animal):
    @override
    name: list[EnglishName]  # type: ignore[assignment]

内容的提问来源于stack exchange,提问作者Ethan Wu juniper

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 05:20:24