I have two dataclasses that I need to add dynamicly generated attribute "code: a lower case version of the name" on both of them
for the first one I did
@dataclass()
class FirstClass:
name: str
code: Optional[str] = field(init=False)
def __post_init__(self):
self.code = self.name.lower()
with init=False I don't need to provide it in the constructor, since it's gonna be generated anyway
however second class is Frozen because I cache its return since it's too big and too expensive to read everytime
@dataclass(frozen=True)
class SecondClass:
name: str
is there anyway to add dynamically generated attribute during init and not post_init because frozen dataclasses are read-only
so I want to do something like
@dataclass(frozen=True)
class SecondClass:
name: str
code: str = name.lower()
One option could be to use object.__setattr__
to bypass the fact that the dataclass is frozen:
from dataclasses import dataclass, field
@dataclass(frozen=True)
class SecondClass:
name: str
code: 'str | None' = field(init=False)
def __post_init__(self, ):
object.__setattr__(self, 'code', self.name.lower())
print(SecondClass('Test'))
Another option could be to add a helper class method new()
which can be used to instantiate a new SecondClass
object:
from dataclasses import dataclass
@dataclass(frozen=True)
class SecondClass:
name: str
code: 'str | None'
@classmethod
def new(cls, name: str):
return cls(name, name.lower())
print(SecondClass.new('Hello'))