I am trying to write an immutable datastructure with the following charicteristics.
- Immutable
- Easy to produce immutable copies with altered fields
- Composable, so that updateing nested data is as easy as updateing un-nessted data
The API im trying to implement is this
a0 = Person(name = 'Jhon', occupation = {'title': 'junear', 'sallary': 30})
a1 = a(name = a0.name + ' Smith')
a2 = a1(occupation = {'title': 'seanear'})
a3 = a2(occupation = {'sallary': 50})
I have writen an implementation like so
from dataclasses import dataclass, replace, field
@dataclass(frozen=True)
class Occupation:
__call__ = replace
title: str
sallary: int
@dataclass(frozen=True)
class Person:
__call__ = replace
name: str
occupation: Occupation
@property
def occupation(self):
return self._occupation
@occupation.setter
def occupation(self, value):
if '_occupation' not in self.__dict__:
print('initalising occupation')
occ = Occupation
else:
print('updating occupation')
occ = self.occupation
if isinstance(value, tuple):
object.__setattr__(self,'_occupation', occ(*value))
elif isinstance(value, dict):
object.__setattr__(self,'_occupation', occ(**value))
elif isinstance(value, Occupation):
object.__setattr(self,'_occupation', value)
However, Im having problems here. a0 works fine, but the rest fail.
I belive the issue is with copying over/ updating the _occupation unmannaged field.
Questions:
- Is there a more simple solution to this that I'm over looking
- How can I accsess the data from the previouse object within the occupation.setter?
- It would be nice if there was a way to generate the boiler plate Ive written, generated when one of the parameters of a frozen dataclass is a frozen dataclass, or even to inline the class definition of the sub-property
Thank you.
Nb:
- in writing this code I have pulled from this thread and I have read this documentation
Defining setter for a property kinda breaks your immutability assumption. You need to construct new
Occupation, and then create newPersonusing it.