10

How can I update the fields of a dataclass using a dict?

Example:

@dataclass
class Sample:
    field1: str
    field2: str
    field3: str
    field4: str

sample = Sample('field1_value1', 'field2_value1', 'field3_value1', 'field4_value1')
updated_values = {'field1': 'field1_value2', 'field3': 'field3_value2'}

I want to do something like

sample.update(updated_values)
Nagabhushan S N
  • 6,407
  • 8
  • 44
  • 87

3 Answers3

10

You don't have to create a new class. You can just do the following:

@dataclass
class Sample:
    field1: str
    field2: str
    field3: str
    field4: str

    def update(self, new):
        for key, value in new.items():
            if hasattr(self, key):
                setattr(self, key, value)


sample = Sample('field1_value1', 'field2_value1', 'field3_value1', 'field4_value1')
updated_values = {'field1': 'field1_value2', 'field3': 'field3_value2'}
sample.update(updated_values)

Edit: Fixed typo class Sample(Updateable): -> class Sample:

Dawierha
  • 139
  • 1
  • 7
  • 1
    1. If you don't define an Updateable class, which class are you inheriting from in the line `class Sample(Updateable):`? 2. The advantage of defining a parent class is that I can inherit from it in multiple dataclasses i.e. I need not write the update method in each of those classes. – Nagabhushan S N Nov 24 '20 at 18:08
  • 1
    1. That was a typo, have fixed it in an edit. 2. That is true if you have multiple dataclasses but unnecessary if you only have one. – Dawierha Nov 25 '20 at 09:46
9

One way is to make a small class and inherit from it:

class Updateable(object):
    def update(self, new):
        for key, value in new.items():
            if hasattr(self, key):
                setattr(self, key, value)

@dataclass
class Sample(Updateable):
    field1: str
    field2: str
    field3: str
    field4: str

You can read this if you want to learn more about getattr and setattr

bb1950328
  • 1,403
  • 11
  • 18
7

Updating the underlying __dict__ seems to work if you have a basic dataclass:

sample.__dict__.update({ 'field1': 'value1' })
Dan Stewart
  • 81
  • 1
  • 3