5
from dataclasses import dataclass
@dataclass
class A:
    x: str
    y: str
    def __post_init__(self):
        self.z = self.x+self.y
a = A('abc', 'def')
a.z
'abcdef'
from dataclasses import asdict
asdict(a)
{'x': 'abc', 'y': 'def'}

As can be seen, z is not be serialized. How to serialize it (other than calling __dict__ on it)?

martineau
  • 119,623
  • 25
  • 170
  • 301
rivu
  • 2,004
  • 2
  • 29
  • 45
  • Have you tried: `b = pickle.loads(pickle.dumps(a))`? It appears that `z` is making it through serialization. It's just not part of the `__str__` function. Or am I misunderstanding your question. – Frank Yellin Nov 04 '20 at 20:55
  • My bad, missed a line there. – rivu Nov 04 '20 at 20:57

1 Answers1

5

You need to include z as a variable when first defining the class but in addition you need to use field to omit it from the __init__ list of parameters.

from dataclasses import dataclass, field, asdict

@dataclass
class A:
    x: str
    y: str
    z: str = field(init=False)
    def __post_init__(self):
        self.z = self.x + self.y

a = A("abc", "def")
a.z
>> 'abcdef'

asdict(a)
>> {'x': 'abc', 'y': 'def', 'z': 'abcdef'}

You can see more here as shown in the docs.

This is because under the hood to create the dictionary, the asdict method fetches the attributes from the __dataclass_fields__ attribute of the object. Since z is not part of those attributes, it will not fetch z when converting the object to a dictionary.

gold_cy
  • 13,648
  • 3
  • 23
  • 45