I was just playing around with the concept of Python dataclasses and abstract classes and what i am trying to achieve is basically create a frozen dataclass but at the same time have one attribute as a property. Below is my code for doing so:
import abc
from dataclasses import dataclass, field
class AbsPersonModel(metaclass=abc.ABCMeta):
@property
@abc.abstractmethod
def age(self):
...
@age.setter
@abc.abstractmethod
def age(self, value):
...
@abc.abstractmethod
def multiply_age(self, factor):
...
@dataclass(order=True, frozen=True)
class Person(AbsPersonModel):
sort_index: int = field(init=False, repr=False)
name: str
lastname: str
age: int
_age: int = field(init=False, repr=False)
def __post_init__(self):
self.sort_index = self.age
@property
def age(self):
return self._age
@age.setter
def age(self, value):
if value < 0 or value > 100:
raise ValueError("Non sensical age cannot be set!")
self._age = value
def multiply_age(self, factor):
return self._age * factor
if __name__ == "__main__":
persons = [
Person(name="Jack", lastname="Ryan", age=35),
Person(name="Jason", lastname="Bourne", age=45),
Person(name="James", lastname="Bond", age=60)
]
sorted_persons = sorted(persons)
for person in sorted_persons:
print(f"{person.name} and {person.age}")
When i run this i get the below error:
Traceback (most recent call last):
File "abstract_prac.py", line 57, in <module>
Person(name="Jack", lastname="Ryan", age=35),
File "<string>", line 4, in __init__
File "abstract_prac.py", line 48, in age
self._age = value
File "<string>", line 3, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field '_age'
How can i get the best of both worlds(dataclasses and also using property along with it)?
Any help would be much appreciated.
__init__
, the same applies for__post_init__
(as in the CPython implemenation, internally__init__
calls__post_init__
). – Wolsey