如何在Pydantic中访问PrivateAttr的更新后值?
问题:Pydantic私有属性复制后属性访问异常
我定义了如下Pydantic类:
from pydantic import BaseModel, PrivateAttr class A(BaseModel): _value: str = PrivateAttr() def __init__(self): self._value = "Initial Value" super().__init__() @property def value(self): return self._value @value.setter def value(self, some_value: str): self._value = some_value def clone(self): return self.copy(update={"_value": "Updated Value"})
当实例化该类并通过clone方法复制实例、更新私有属性_value后,打印实例能看到副本的_value已更新,但访问副本的value属性却仍得到初始值。执行以下测试代码:
a = A() b = a.clone() print([a, b]) print(a.value) print(b.value)
得到输出:
[A(), A(_value='Updated Value')] Initial Value Initial Value
请问如何正确获取更新后的值?
原因分析
Pydantic的copy()方法处理私有属性时,会将更新的私有属性存储在实例的__private_attributes__字典中,但自定义的@property直接访问的是__init__中创建的普通实例属性self._value,两者并非同一存储位置。
在__init__中直接给self._value赋值时,会在实例上生成一个独立的普通属性,而Pydantic管理的私有属性实际由__private_attributes__维护。copy()更新的是Pydantic管控的私有属性,value属性读取的却是手动创建的_value实例属性,因此无法获取到更新后的值。
解决方案
方案1:统一使用Pydantic私有属性访问逻辑
修改value属性的读写逻辑,直接操作Pydantic管理的私有属性存储:
from pydantic import BaseModel, PrivateAttr class A(BaseModel): _value: str = PrivateAttr(default="Initial Value") def __init__(self, **data): super().__init__(**data) @property def value(self): return self.__private_attributes__["_value"].get(self) @value.setter def value(self, some_value: str): self.__private_attributes__["_value"].set(self, some_value) def clone(self): return self.copy(update={"_value": "Updated Value"})
方案2:通过Pydantic初始化逻辑设置私有属性
避免在__init__中直接赋值self._value,改用Pydantic的初始化参数传递私有属性值:
from pydantic import BaseModel, PrivateAttr class A(BaseModel): _value: str = PrivateAttr() def __init__(self): super().__init__(_value="Initial Value") @property def value(self): return self._value @value.setter def value(self, some_value: str): self._value = some_value def clone(self): return self.copy(update={"_value": "Updated Value"})
修改后再次运行测试代码,b.value将正确返回"Updated Value"。
内容的提问来源于stack exchange,提问作者Sujan
相关产品推荐
相关产品推荐

