具有复杂字段的数据类继承

Dataclass inheritance with complex fields

我希望使用 Python 中的数据classes 创建一个基础 class 和几个派生的 classes。这些 classes 将包含复杂的属性,例如字典。我希望派生的 classes 仅更改基 class 定义的字典的一部分,这可能吗?还是我用普通的旧 classes 更好?
代码片段中显示的是当前情况,这在代码重复方面似乎很浪费。
在这个例子中,我可以定义一个接受单个参数而不是 lambda 的函数,但在现实世界的例子中,我必须为每个这样的情况定义一个函数,这会很麻烦。

from dataclasses import dataclass, field


@dataclass
class BaseDataClass:
    simple_field_one: int = 100
    simple_field_two: int = 200
    complex_field: dict = field(default_factory=lambda: {
        'x': 0.1,
        'y': ['a', 'b']
    })


@dataclass
class DerivedDataClass(BaseDataClass):
    simple_field_two: int = 300  # this is easy
    complex_field: dict = field(default_factory=lambda: {
        'x': 0.1,
        'y': ['a', 'c']
    })  # this is wasteful. All I changed was complex_field['y'][1]

我以这种方式广泛使用数据类,它似乎工作得很好。

然而,我所做的一个不同是使复杂字段成为它们自己的数据类(参见 Python nested dataclasses ...is this valid?)。

您可能想要考虑这种方法,看看它如何帮助您减少您所看到的一些冗长内容。

这可能是显而易见的,但如果更改非常小,使用 __post_init__ 应用它而不是重新定义字段会很方便:

from dataclasses import dataclass, field


@dataclass
class BaseDataClass:
    simple_field_one: int = 100
    simple_field_two: int = 200
    complex_field: dict = field(default_factory=lambda: {
        'x': 0.1,
        'y': ['a', 'b']
    })


@dataclass
class DerivedDataClass(BaseDataClass):
    simple_field_two: int = 300

    def __post_init__(self):
        self.complex_field['y'][1] = 'c'

略有不同的替代方案,以防您希望能够在初始化期间控制对 complex_field 的更新:

from dataclasses import dataclass, field, InitVar

...

@dataclass
class DerivedDataClass(BaseDataClass):
    simple_field_two: int = 300
    # having a mutable default is fine here, since its reference isn't kept around
    # and we don't change it during post_init
    complex_update: InitVar[dict] = {'y': ['a', 'c']}

    def __post_init__(self, complex_update):
        self.complex_field.update(complex_update)