python - 在 Python 中使用卡住数据类时如何使用属性 setter

标签 python abstract-class python-3.7 python-dataclasses

我只是在玩弄 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, 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}")

当我运行它时,出现以下错误:

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'

我怎样才能两全其美(数据类和同时使用属性)?

如有任何帮助,我们将不胜感激。

最佳答案

您可以执行 frozen 初始化器 in dataclasses itself does 的操作并使用 object.__setattr__ 来赋值。给定您的抽象类,此数据类定义应该有效:

@dataclass(order=True, frozen=True)
class Person:
    sort_index: int = field(init=False, repr=False)
    name: str
    lastname: str
    age: int
    _age: int = field(init=False, repr=False)  # can actually be omitted

    def __post_init__(self):
        object.__setattr__(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!")
        object.__setattr__(self, '_age', value)

    def multiply_age(self, factor):
        return self._age * factor

运行你的测试套件现在应该返回预期的结果

Jack and 35
Jason and 45
James and 60

这是有效的,因为将数据类设置为 frozen 会禁用该类自己的 __setattr__ 并使其仅引发您看到的异常。它的父类(super class)(始终包含 object)的任何 __setattr__ 仍然有效。

关于python - 在 Python 中使用卡住数据类时如何使用属性 setter ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59221782/

相关文章:

c++ - 模板运算符返回对抽象类的引用

c++ - 抽象基类谜题

python - 整数网格

python - 在数据框中查找并替换半通用字符串?

python - keras:样本权重多重不平衡输出

c++ - 指向采用抽象参数的函数的指针

python - 协程中的异步运行时错误 : no running event loop

python - 使用 OpenStack Nova 异常

python - openpyxl: merged_cell_ranges 和 merged_cells 都是空的

Python CV2 提取带字幕的视频帧