Как можно использовать установщик свойств при использовании замороженных классов данных в Python

Я просто играл с концепцией классов данных Python и абстрактных классов, и то, что я пытаюсь достичь, - это в основном создать замороженный класс данных, но в то же время иметь один атрибут в качестве свойства. Ниже мой код для этого:

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):
        ...

    @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}")

Когда я запускаю это, я получаю следующую ошибку:

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'

Как я могу получить лучшее из обоих миров (классы данных, а также использование свойства вместе с ним)?

Любая помощь приветствуется.


person user1867151    schedule 06.12.2019    source источник
comment
Я повторю свой комментарий из вашего последнего вопроса. См. stackoverflow.com/q/57791679/2750819: хотя ответ в основном касается __init__, то же самое относится и к __post_init__ (как в реализации CPython внутренне __init__ вызывает __post_init__).   -  person Kent Shikama    schedule 08.12.2019


Ответы (1)