Pydantic嵌套模型默认值实例化时机及相关异常行为疑问
现象底层原理
你观察到的两个矛盾点(DemoModel.__init__仅调用一次、修改c1.demo不影响c2.demo)是Pydantic处理嵌套模型默认值的特殊逻辑共同导致的:
- 你理解的类定义阶段初始化一次是对的:Python类字段的默认值会在类被定义时计算,所以
CompositeModel类加载时就会执行一次DemoModel()生成全局默认实例,你的打印日志只会触发一次。 - 但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
相关产品推荐
相关产品推荐

