如何在 Python 数据类中使用 __post_init__ 方法

use*_*151 9 python-3.7 python-dataclasses

我正在尝试使用Python中的数据类,我想做的是在我的类中拥有一个计算字段,并将 sort_index 字段添加到调用中,但也希望将其冻结,以便我无法修改任何属性定义后的此类。下面是我的代码:

from dataclasses import dataclass, field

def _get_year_of_birth(age: int, current_year: int=2019):
    return current_year - age

@dataclass(order=True, frozen=True)
class Person():
    sort_index: int = field(init=False, repr=False)
    name: str
    lastname: str
    age: int
    birthyear: int = field(init=False)


    def __post_init__(self):
        self.sort_index = self.age
        self.birthyear = _get_year_of_birth(self.age)



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} and year of birth is : {person.birthyear}")
Run Code Online (Sandbox Code Playgroud)

看来我无法在类中设置自定义排序字段,也无法创建从其他属性计算得出的任何属性,因为我使用的是 freeze 。当我运行上面的代码时,出现以下错误:

Traceback (most recent call last):
  File "dataclasses_2.py", line 30, in <module>
    Person(name="Jack", lastname="Ryan", age=35),
  File "<string>", line 5, in __init__
  File "dataclasses_2.py", line 23, in __post_init__
    self.sort_index = self.age
  File "<string>", line 3, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field 'sort_index'
Run Code Online (Sandbox Code Playgroud)

有更好的方法吗?请帮忙

mag*_*mar 8

问题是您正在尝试设置冻结对象的字段。这里有两个选择。第一个选择是frozen=True从数据类规范中删除。其次,如果您仍然想冻结 Person 实例,那么您应该使用 method 初始化字段__setattr__。因此,你的 post_init 方法将变成:

def __post_init__(self):
    object.__setattr__(self, 'sort_index', self.age)
    object.__setattr__(self, 'birthyear', _get_year_of_birth(self.age)
Run Code Online (Sandbox Code Playgroud)

  • 这个答案是不正确的。`self.__setattr__` 正是首先引发 `FrozenInstanceError` 的原因。你想要的是`object.__setattr__(self, ...)`,如上面已经提到的答案中详细说明的:stackoverflow.com/a/54119384/8960865 (3认同)