Reputation: 1618
I am working with frozen dataclasses in Python. My goal is to create a dataclass with its frozen attributes. However, one of the attributes is a function of the other ones. I want my class to be frozen (once it has been instantiated it can't be changed), but I can't find a way to specify the value of an attribute inside the class with a method.
As an example, let's suppose to have the following simple class:
@dataclasses.dataclass(frozen=True)
class Car:
color: str
size: int
model: str
price: float
The price of the car is function of its color, size and model. As an example:
def _compute_price(self, color, size, model):
if color == 'red':
color_surplus = 10
else:
color_surplus = 0
if size > 10:
size_surplus = 10
else:
size_surplus = 5
if model == 'mustang':
model_surplus = 100
else:
model_surplus = 0
self.price = color_surplus + size_surplus + model_surplus
I would like to create my car like:
car = Car('red', 15, 'mustang')
And automatically use the above sample function inside my class to initialize the missing price
attribute. However, as soon as I specify self.price
, Python tells me that it is a read only attribute and thus non-assignable.
I also tried to use the __init__
function, but I still have the same problem:
@dataclasses.dataclass(frozen=True)
class Car:
def __init__(self, color: str, size: int, model: str, price: float):
self.color = color #error here
...
...
Any solutions? My goal is to use a frozen dataclass while being able to specify an attribute with a private function (included in the class) of the other ones
Upvotes: 3
Views: 1543
Reputation: 56
Make price a property, wich are read only if you don't create a setter:
@property
def price(self):
if self.color == 'red':
color_surplus = 10
else:
color_surplus = 0
if self.size > 10:
size_surplus = 10
else:
size_surplus = 5
if self.model == 'mustang':
model_surplus = 100
else:
model_surplus = 0
return color_surplus + size_surplus + model_surplus
You can also use cached_property instead of property to not recompute the value each time you call it
Upvotes: 4