Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 929
BayerSe Avatar asked Apr 18 '18 20:04

BayerSe


People also ask

What is __ Post_init __?

The post-init function is an in-built function in python and helps us to initialize a variable outside the __init__ function. post-init function in python.

What is @dataclass in Python?

Python introduced the dataclass in version 3.7 (PEP 557). The dataclass allows you to define classes with less code and more functionality out of the box. The following defines a regular Person class with two instance attributes name and age : class Person: def __init__(self, name, age): self.name = name self.age = age.

What is @dataclass?

A data class is a class typically containing mainly data, although there aren't really any restrictions. It is created using the new @dataclass decorator, as follows: from dataclasses import dataclass @dataclass class DataClassCard: rank: str suit: str.

How does Dataclass work in Python?

DataClass in Python DataClasses are like normal classes in Python, but they have some basic functions like instantiation, comparing, and printing the classes already implemented. Parameters: init: If true __init__() method will be generated. repr: If true __repr__() method will be generated.


2 Answers

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.

like image 190
wim Avatar answered Oct 18 '22 20:10

wim


I know the question is about dataclass, but if you're using attr.s instead then you can use attr.evolve instead of 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) 
like image 23
Florian Brucker Avatar answered Sep 21 '22 19:09

Florian Brucker