将所有字段从一个数据类实例复制到另一个实例的最简单方法?
Easiest way to copy all fields from one dataclass instance to another?
假设您已经定义了一个 Python 数据类:
@dataclass
class Marker:
a: float
b: float = 1.0
将值从实例 marker_a
复制到另一个实例 marker_b
的最简单方法是什么?
这是我尝试实现的示例:
marker_a = Marker(1.0, 2.0)
marker_b = Marker(11.0, 12.0)
# now some magic happens which you hopefully can fill in
print(marker_b)
# result: Marker(a=1.0, b=2.0)
作为边界条件,我不希望创建新实例并将其分配给marker_b
。
好的,我可以遍历所有定义的字段并逐个复制值,但我想必须有更简单的方法。
@dataclass
class Marker:
a: float
b: float = 1.0
marker_a = Marker(0.5)
marker_b = Marker(**marker_a.__dict__)
marker_b
# Marker(a=0.5, b=1.0)
如果您不想创建新实例,试试这个:
marker_a = Marker(1.0, 2.0)
marker_b = Marker(11.0, 12.0)
marker_b.__dict__ = marker_a.__dict__.copy()
# result: Marker(a=1.0, b=2.0)
不确定这是否被认为是一个糟糕的 hack...
我认为遍历字段可能是最简单的方法。我能想到的所有其他选项都涉及创建一个新对象。
from dataclasses import fields
marker_a = Marker(5)
marker_b = Marker(0, 99)
for field in fields(Marker):
setattr(marker_b, field.name, getattr(marker_a, field.name))
print(marker_b) # Marker(a=5, b=1.0)
dataclasses.replace
函数 return 是对象的新副本。
不传递任何更改,它将 return 一个没有修改的副本:
>>> import dataclasses
>>> @dataclasses.dataclass
... class Dummy:
... foo: int
... bar: int
...
>>> dummy = Dummy(1, 2)
>>> dummy_copy = dataclasses.replace(dummy)
>>> dummy_copy.foo = 5
>>> dummy
Dummy(foo=1, bar=2)
>>> dummy_copy
Dummy(foo=5, bar=2)
请注意,这是一个浅拷贝。
编辑以解决评论:
如果不需要副本,我可能会选择以下内容:
for key, value in dataclasses.asdict(dummy).items():
setattr(some_obj, key, value)
另一个可能更优雅的选项:
import dataclasses
marker_a = Marker(1.0, 2.0)
marker_b = Marker(**dataclasses.asdict(marker_a))
假设您已经定义了一个 Python 数据类:
@dataclass
class Marker:
a: float
b: float = 1.0
将值从实例 marker_a
复制到另一个实例 marker_b
的最简单方法是什么?
这是我尝试实现的示例:
marker_a = Marker(1.0, 2.0)
marker_b = Marker(11.0, 12.0)
# now some magic happens which you hopefully can fill in
print(marker_b)
# result: Marker(a=1.0, b=2.0)
作为边界条件,我不希望创建新实例并将其分配给marker_b
。
好的,我可以遍历所有定义的字段并逐个复制值,但我想必须有更简单的方法。
@dataclass
class Marker:
a: float
b: float = 1.0
marker_a = Marker(0.5)
marker_b = Marker(**marker_a.__dict__)
marker_b
# Marker(a=0.5, b=1.0)
如果您不想创建新实例,试试这个:
marker_a = Marker(1.0, 2.0)
marker_b = Marker(11.0, 12.0)
marker_b.__dict__ = marker_a.__dict__.copy()
# result: Marker(a=1.0, b=2.0)
不确定这是否被认为是一个糟糕的 hack...
我认为遍历字段可能是最简单的方法。我能想到的所有其他选项都涉及创建一个新对象。
from dataclasses import fields
marker_a = Marker(5)
marker_b = Marker(0, 99)
for field in fields(Marker):
setattr(marker_b, field.name, getattr(marker_a, field.name))
print(marker_b) # Marker(a=5, b=1.0)
dataclasses.replace
函数 return 是对象的新副本。
不传递任何更改,它将 return 一个没有修改的副本:
>>> import dataclasses
>>> @dataclasses.dataclass
... class Dummy:
... foo: int
... bar: int
...
>>> dummy = Dummy(1, 2)
>>> dummy_copy = dataclasses.replace(dummy)
>>> dummy_copy.foo = 5
>>> dummy
Dummy(foo=1, bar=2)
>>> dummy_copy
Dummy(foo=5, bar=2)
请注意,这是一个浅拷贝。
编辑以解决评论:
如果不需要副本,我可能会选择以下内容:
for key, value in dataclasses.asdict(dummy).items():
setattr(some_obj, key, value)
另一个可能更优雅的选项:
import dataclasses
marker_a = Marker(1.0, 2.0)
marker_b = Marker(**dataclasses.asdict(marker_a))