如何根据初始化参数实例化对应版本的Pydantic模型?
实现版本化MessageModel的几种方案
方案1:自定义工厂函数
最简单直接的方式是写一个工厂函数,根据传入的version参数返回对应版本的模型实例:
from typing import Literal from pydantic import BaseModel class MessageModelV1(BaseModel): version: Literal[1] bar: str class MessageModelV2(BaseModel): version: Literal[2] foo: str def MessageModel(**kwargs): version = kwargs.get("version") if version == 1: return MessageModelV1(**kwargs) elif version == 2: return MessageModelV2(**kwargs) else: raise ValueError(f"Unsupported version: {version}") # 调用示例 model_v1 = MessageModel(version=1, bar="test_v1") model_v2 = MessageModel(version=2, foo="test_v2")
新增版本时,只需要在工厂函数里添加对应版本的判断分支即可,逻辑清晰易懂。
方案2:利用Pydantic Union自动判别
Pydantic原生支持Union类型的自动解析,只要各个版本模型的version是唯一的Literal值,就能自动匹配对应模型:
from typing import Literal, Union from pydantic import BaseModel, TypeAdapter class MessageModelV1(BaseModel): version: Literal[1] bar: str class MessageModelV2(BaseModel): version: Literal[2] foo: str # 封装成支持关键字参数调用的形式 def MessageModel(**kwargs): return TypeAdapter(Union[MessageModelV1, MessageModelV2]).validate_python(kwargs) # 调用示例 model_v1 = MessageModel(version=1, bar="test_v1") model_v2 = MessageModel(version=2, foo="test_v2")
这种方式完全依托Pydantic的特性,新增版本时仅需把新模型加入Union集合,不需要修改核心逻辑。
方案3:自定义代理类
如果希望MessageModel保持类的形式而非函数,可以通过重写__new__方法实现代理:
from typing import Literal from pydantic import BaseModel class MessageModelV1(BaseModel): version: Literal[1] bar: str class MessageModelV2(BaseModel): version: Literal[2] foo: str class MessageModel: def __new__(cls, **kwargs): version = kwargs.get("version") if version == 1: return MessageModelV1(**kwargs) elif version == 2: return MessageModelV2(**kwargs) else: raise ValueError(f"Unsupported version: {version}") # 调用示例 model_v1 = MessageModel(version=1, bar="test_v1") model_v2 = MessageModel(version=2, foo="test_v2")
这个方式让MessageModel完全以类的形态存在,调用方式和你期望的完全一致,新增版本时在__new__方法里添加对应分支即可。
内容的提问来源于stack exchange,提问作者Phil997
相关产品推荐
相关产品推荐

