将所有字段从一个数据类实例复制到另一个实例的最简单方法?

Tom*_*ohl 15 python python-dataclasses

假设您已经定义了一个 Python 数据类:

@dataclass
class Marker:
    a: float
    b: float = 1.0
Run Code Online (Sandbox Code Playgroud)

将值从一个实例复制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)
Run Code Online (Sandbox Code Playgroud)

作为边界条件,我不想创建新实例并将其分配给marker_b. 好的,我可以遍历所有定义的字段并一个一个复制值,但我想必须有一种更简单的方法。

Dan*_*rez 35

dataclasses.replace函数返回对象的新副本。不传递任何更改,它将返回一个没有修改的副本:

>>> 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)
Run Code Online (Sandbox Code Playgroud)

请注意,这是一个浅拷贝。

编辑以解决评论:

如果不需要副本,我可能会采用以下方法:

>>> 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)
Run Code Online (Sandbox Code Playgroud)

  • 这不是问题的直接答案,但可以在 Google 中找到作为如何创建副本问题的答案,所以无论如何感谢您的回答! (6认同)
  • 问题具体是关于如何将字段复制到现有实例中。 (2认同)

r.o*_*ook 9

@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)
Run Code Online (Sandbox Code Playgroud)

如果您不想创建新实例,请尝试以下操作:

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)
Run Code Online (Sandbox Code Playgroud)

但不确定这是否被认为是一个糟糕的黑客......


Pat*_*ugh 7

我认为循环字段可能是最简单的方法。我能想到的所有其他选项都涉及创建一个新对象。

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)
Run Code Online (Sandbox Code Playgroud)


Nur*_*r L 6

另一种可能更优雅的选择:

import dataclasses

marker_a = Marker(1.0, 2.0)
marker_b = Marker(**dataclasses.asdict(marker_a))
Run Code Online (Sandbox Code Playgroud)