how to add values for frozen dataclasses during initialization

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() 

3 Answers

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')) 
6

Another approach, using @property - doesn't store code in the class but exposes it as an attribute:

@dataclass(frozen=True) class SecondClass: name: str @property def code(self): return self.name.lower() print(SecondClass('Me').code) 

Result:

me 
1

I'd use a combination of the first approach with a custom creation function:

@dataclass(frozen=True) class SecondClass: name: str code: Optional[str] def create_second(name): return SecondClass(name, name.lower()) print(create_second('Me')) 

Result:

SecondClass(name='Me', code='me') 
1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like