Search code examples
pythonpython-3.7python-dataclasses

Replace attributes in Data Class objects


I'd like to replace the attributes of a dataclass instance, analogous to namedtuple._replace(), i.e. making an altered copy of the original object:

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)

This returns:

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

How can I mimic this functionality in dataclass objects?


Solution

  • The dataclasses module has a helper function for field replacement on instances (docs)

    from dataclasses import replace
    

    Usage differs from collections.namedtuple, where the functionality was provided by a method on the generated type (Side note: namedtuple._replace is documented/public API, using an underscore on the name was called a "regret" by the author, see link at end of answer).

    >>> 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)
    

    For more background of the design, see the PyCon 2018 talk - Dataclasses: The code generator to end all code generators. The replace API is discussed in depth, along with other design differences between namedtuple and dataclasses, and some performance comparisons are shown.