替换数据类对象中的属性

Bay*_*rSe 6 python python-3.7 python-dataclasses

我想替换数据类实例的属性,类似于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)
Run Code Online (Sandbox Code Playgroud)

返回:

U(x=1)
U(x=-1)
V(x=1)
Run Code Online (Sandbox Code Playgroud)

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

wim*_*wim 8

Python数据类模块具有一个公共API,用于在数据类实例上进行字段替换,如此处所述。此功能由模块级帮助程序功能提供:

from dataclasses import replace
Run Code Online (Sandbox Code Playgroud)

用法与的用法不同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)
Run Code Online (Sandbox Code Playgroud)

有关设计的更多背景信息,请参见PyCon 2018对话-数据类:代码生成器以结束所有代码生成器。该replaceAPI在深度所讨论的,与之间的其它设计差异沿namedtupledataclasses一些性能比较以及。

  • 当拥有(伪)不可变对象(例如冻结数据类)时,“replace”非常有用。它们在函数式编程中非常常见,您不会改变原始对象,而是返回一个新对象,其中除您“替换”的字段外,所有字段都相等。 (9认同)
  • 我有点想将 Replacec 作为“方法”而不是函数,因为它似乎在调用代码中嵌入了某种数据类的假设。 (2认同)