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

如何在Pydantic泛型基类中实现泛型类型的默认工厂?

Pydantic泛型模型字段默认工厂的实现方案

问题场景

想要创建一个泛型基模型,让字段默认使用对应类型的默认工厂,编写了如下代码:

from pydantic import BaseModel, Field
from pydantic.generics import GenericModel, Generic
from typing import TypeVar, Generic, Optional

T = TypeVar("T")


class Material(GenericModel, Generic[T]):
    value: T = Field(default_factory=T)


Material[float](value=1)
Material[float](value="1 ")
Material[Optional[float]]()

运行时触发如下错误:

Traceback (most recent call last):
  File "/home/tom/.config/JetBrains/PyCharm2022.2/scratches/tmp.py", line 14, in <module>
    Material[Optional[float]]()
  File "pydantic/main.py", line 340, in pydantic.main.BaseModel.__init__
  File "pydantic/main.py", line 1066, in pydantic.main.validate_model
  File "pydantic/fields.py", line 439, in pydantic.fields.ModelField.get_default
TypeError: 'TypeVar' object is not callable

问题:是否可以为泛型类型设置默认工厂?


问题根源

直接将TypeVar对象T传给default_factory不可行:

  • 当实例化Material[Optional[float]]时,T绑定的是Optional[float],这是一个类型注解而非可调用的工厂函数
  • 即使是float这类可调用的基本类型,default_factory=T的写法在模型定义阶段仍会将T视为未绑定的TypeVar对象,无法正确解析

可行实现方案

通过动态解析泛型类型参数,自定义默认生成逻辑,代码如下:

from pydantic import BaseModel, Field
from pydantic.generics import GenericModel, Generic
from typing import TypeVar, Optional, get_args, get_origin

T = TypeVar("T")

class Material(GenericModel, Generic[T]):
    value: T = Field(default_factory=lambda self: self._get_default())
    
    def _get_default(self):
        # 获取当前模型绑定的泛型类型
        bound_type = get_args(self.__orig_bases__[0])[0]
        type_origin = get_origin(bound_type)
        
        # 处理Optional类型,返回None
        if type_origin is Optional:
            return None
        # 基本类型调用自身生成默认值(如float()→0.0,str()→"")
        try:
            return bound_type()
        except TypeError:
            # 复杂类型可根据需求返回自定义默认值,此处返回None
            return None

# 测试验证
print(Material[float](value=1))          # Material(value=1.0)
print(Material[float](value="1 "))       # Material(value=1.0)
print(Material[Optional[float]]())       # Material(value=None)
print(Material[str]())                   # Material(value='')

核心逻辑说明

  1. 解析泛型绑定类型:通过self.__orig_bases__获取当前实例绑定的泛型参数,再用get_args提取具体类型
  2. 处理Optional类型:利用get_origin识别Optional类型,直接返回None
  3. 适配基本类型:对可调用的基本类型(如int/float/str),调用自身生成默认值;对不可调用的复杂类型,返回自定义默认值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 17:11:16