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

Pydantic嵌套模型默认值实例化时机及相关异常行为疑问

现象底层原理

你观察到的两个矛盾点(DemoModel.__init__仅调用一次、修改c1.demo不影响c2.demo)是Pydantic处理嵌套模型默认值的特殊逻辑共同导致的:

  1. 你理解的类定义阶段初始化一次是对的:Python类字段的默认值会在类被定义时计算,所以CompositeModel类加载时就会执行一次DemoModel()生成全局默认实例,你的打印日志只会触发一次。
  2. 但Pydantic不会直接把这个全局默认实例绑定到每个新建的CompositeModel实例上,为了避免不同实例共享同一个可变默认值的问题,它会在实例化父模型时,对嵌套模型的默认值执行深拷贝:走的是Pydantic内部的序列化-反序列化逻辑生成新实例,不会调用你重写的DemoModel.__init__方法,所以你看不到新增的打印日志,但两个demo字段确实指向不同对象,修改其中一个不会影响另一个。

这就解释了你看到的所有现象:初始拷贝值完全一致所以c1==c2成立,两个实例指向不同对象所以修改后断言失败,全程只有类加载时的一次__init__调用。

Field动态默认值方案

可以实现相同效果,而且这是官方更推荐的动态默认值实现方式,比自定义validator写法更简洁。你提到的dynamic_factory是记忆偏差,Pydantic V1、V2中对应的参数均为default_factory,写法如下:

from pydantic import BaseModel, Field

class CompositeModel3(BaseModel):
    demo: DemoModel = Field(default_factory=DemoModel)

每次实例化CompositeModel3时,Pydantic都会自动调用DemoModel()生成新的子模型实例,会正常触发__init__方法的打印,不同实例的demo完全独立,完全符合你的预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 18:12:03