25

我想替换数据类实例的属性类似于namedtuple._replace(),即制作原始对象的更改副本:

from dataclasses import dataclass
from collections import namedtuple

U = namedtuple("U", "x")

@dataclass
class V:
    x: int

u = U(x=1)
u_ = u._replace(x=-1)
v = V(x=1)

print(u)
print(u_)
print(v)

这将返回:

U(x=1)
U(x=-1)
V(x=1)

如何在数据类对象中模仿此功能?

4

4 回答 4

40

Python 数据类模块有一个用于在数据类实例上进行字段替换的公共 API,记录在此处。此功能由模块级辅助函数提供:

from dataclasses import replace

用法不同于collections.namedtuple,其中此功能是通过生成类型上的方法提供的(旁注: namedtuple._replace已记录/公开。此名称选择被作者称为“遗憾” - 请参阅答案末尾的链接)。

示例用法:

>>> from dataclasses import dataclass, replace
>>> @dataclass
... class V:
...     x: int
...     y: int
...     
>>> v = V(1, 2)
>>> v_ = replace(v, y=42)
>>> v
V(x=1, y=2)
>>> v_
V(x=1, y=42)

有关设计的更多背景信息,请参阅 PyCon 2018 演讲 - Dataclasses: The code generator to end all code generators。深入讨论了replaceAPI,以及它们之间的其他设计差异namedtuple以及dataclasses一些性能比较。

于 2018-05-13T19:21:31.017 回答
1

我知道问题是关于dataclass,但是如果您使用的是 ,attr.s那么您可以使用attr.evolve代替dataclasses.replace

import attr

@attr.s(frozen=True)
class Foo:
    x = attr.ib()
    y = attr.ib()

foo = Foo(1, 2)
bar = attr.evolve(foo, y=3)
于 2020-12-16T06:59:54.490 回答
0

dataclass只是用于自动创建特殊__init__方法和许多其他基于类型注释属性的“样板”方法的语法糖。

一旦创建了类,它就和其他类一样,它的属性可以被覆盖并且实例可以被复制,例如

import copy

v_ = copy.deepcopy(v)
v_.x = -1

根据属性是什么,您可能只需要copy.copy.

于 2018-04-18T20:34:15.143 回答
-1
@dataclass()
class Point:
    x: float = dataclasses.Field(repr=True, default=0.00, default_factory=float, init=True, hash=True, compare=True,
                                 metadata={'x_axis': "X Axis", 'ext_name': "Point X Axis"})
    y: float = dataclasses.Field(repr=True, default=0.00, default_factory=float, init=True, hash=True, compare=True,
                                 metadata={'y_axis': "Y Axis", 'ext_name': "Point Y Axis"})

Point1 = Point(13.5, 455.25)
Point2 = dataclasses.replace(Point1, y=255.25)

print(Point1, Point2)
于 2021-03-31T15:23:38.630 回答