将对象字段复制到另一个对象,同时排除多个字段



我有一个pydantic类:

class SomeData(BaseModel):
id: int
x: str
y: str
z: str

假设我有两个这个类的对象obj1 obj2

是否有任何简单的方法,我可以复制obj2,到obj1,而忽略字段的子集?例如,复制所有SomeData字段,除了[id,z]

查看model.copy(...)(docs)和model.dict(...)(docs) -特别是update: dictexclude: set[str]参数。

给定SomeData的两个实例(obj1和obj2),用obj2中不包括某些字段的值更新obj1变量:

obj1 = SomeData(id=1, x='x', y='y', z='z')
obj2 = SomeData(id=2, x='x2', y='y2', z='z2')
obj1 = obj1.copy(update=obj2.dict(exclude={"id", "z"}))
# obj1 -> SomeData(id=1, x='x2', y='y2', z='z')

注意,这会创建一个新的副本,而不是改变原来的副本。


从obj1创建obj2(不包括字段),可以直接使用.copy(exclude=...):

obj1 = SomeData(id=1, x='x', y='y', z='z')
obj2 = obj1.copy(exclude={"id", "z"})
# obj2 -> SomeData(x='x', y='y')

如果obj1obj2都已经初始化,并且你想用obj2上这些字段的值覆盖obj1的某些字段,你需要自己实现。

这样就可以了:

from collections.abc import Container, Iterable
from typing import Any
from pydantic import BaseModel

class SomeData(BaseModel):
id: int
x: str
y: str
z: str
def update(
self,
other: Iterable[tuple[str, Any]],
exclude: Container[str] = (),
) -> None:
for field_name, value in other:
if field_name not in exclude:
setattr(self, field_name, value)

obj1 = SomeData(id=1, x="a", y="b", z="c")
obj2 = SomeData(id=2, x="foo", y="bar", z="baz")
obj1.update(obj2, exclude={"id", "z"})
print(obj1)

输出:id=1 x='foo' y='bar' z='c'

最新更新