如何在Pydantic中使用抽象基类子类实现多态列表?
解决Pydantic继承场景下子类字段被忽略的问题
这个问题是Pydantic处理多态类型时的常见情况——默认情况下,当你声明父类类型的列表时,Pydantic只会解析父类定义的字段,子类的额外字段会被直接丢弃。要让events正确成为Base子类的实例列表,有两种实用的解决方法:
方法1:使用鉴别器(Discriminator,推荐Pydantic v2+)
这是Pydantic官方推荐的多态处理方案,通过添加一个鉴别字段让Pydantic自动识别不同子类。步骤如下:
- 在父类
Base中定义一个鉴别字段(比如type),用来区分不同子类; - 每个子类固定这个字段的取值,标识自身类型;
- 用
Annotated+Union结合Discriminator定义子类的联合类型; - 在
Response中使用这个联合类型的列表。
完整代码示例:
from abc import ABC from typing import List, Annotated, Union from pydantic import BaseModel, Discriminator class Base(BaseModel, ABC): common: int type: str # 鉴别字段,用于区分子类 class Child1(Base): child1: int type: str = "child1" # 固定子类标识 class Child2(Base): child2: int type: str = "child2" # 定义带鉴别器的联合类型,指定用`type`字段判断子类 Event = Annotated[Union[Child1, Child2], Discriminator("type")] class Response(BaseModel): events: List[Event] # 注意传入的字典要包含`type`字段 events = [ {'common':1, 'type': 'child1', 'child1': 10}, {'common': 2, 'type': 'child2', 'child2': 20} ] resp = Response(events=events) print(resp.events) # 输出:[Child1(common=1, type='child1', child1=10), Child2(common=2, type='child2', child2=20)]
这样Pydantic就能根据type字段的值自动匹配对应的子类,完整保留所有字段。
方法2:手动解析子类实例(无需修改模型结构)
如果不想在模型中添加额外的鉴别字段,可以手动判断每个字典的字段,将其解析为对应的子类实例,再传入Response:
from abc import ABC from typing import List from pydantic import BaseModel, parse_obj_as class Base(BaseModel, ABC): common: int class Child1(Base): child1: int class Child2(Base): child2: int class Response(BaseModel): events: List[Base] events = [{'common':1, 'child1': 10}, {'common': 2, 'child2': 20}] # 手动解析每个事件到对应子类 parsed_events = [] for event in events: if 'child1' in event: parsed_events.append(Child1(**event)) elif 'child2' in event: parsed_events.append(Child2(**event)) resp = Response(events=parsed_events) print(resp.events) # 输出:[Child1(common=1, child1=10), Child2(common=2, child2=20)]
这种方式的缺点是需要自己维护字段和子类的映射关系,当子类较多时会比较繁琐,但胜在不需要修改原有模型结构。
补充:如果使用Pydantic v1,鉴别器的语法略有不同,需要在
Union类型中通过Field(discriminator="type")配置,或者在模型的Config类中设置discriminator字段,核心逻辑是一致的。
内容的提问来源于stack exchange,提问作者Apostolos
相关产品推荐
相关产品推荐

