简体   繁体   English

Python数据类从父数据类继承部分属性

[英]Python dataclasses inheritance part of attributes from parent dataclass

I constructed multiple base dataclass .我构建了多个基础dataclass Now I want to construct a child dataclass inheriting from these base classes, but may inherit part of attributes defined in some base classes.现在我想构造一个继承自这些基类的子dataclass类,但可能会继承某些基类中定义的部分属性。 Examples can be:示例可以是:

import dataclasses

@dataclasses.dataclass
class A:
    a: int = None
    b: float = None
    c: str = None

@dataclasses.dataclass
class B:
    d: int = None
    b: float = 3.5

@dataclasses.dataclass
class C:
    e: int = None
    f: float = 3.5
    g: int = None

@dataclasses.dataclass
class D(A, B):
    def __post_init__(self):
        for _field, _field_property in C.__dataclass_fields__.items():
            if _field != "g":
                setattr(self, _field, _field_property.default)

Namely, I want to construct a child class D inheriting A and B , and attributes in C except g .即,我想构造一个继承AB的子类D ,以及Cg之外的属性。 Checking the child class D检查子类D

>>> D.__dataclass_fields__.keys() # got dict_keys(['d', 'b', 'a', 'c'])
>>> d = D(a=4, b=2, c=5, d=3.4, e=2.1, g=55)
Traceback (most recent call last):
  File "<pyshell#77>", line 1, in <module>
    d = D(a=4, b=2, c=5, d=3.4, e=2.1, g=55)
TypeError: __init__() got an unexpected keyword argument 'e'

And

>>> D.__dict__.keys()
dict_keys(['__module__', '__post_init__', '__doc__', '__dataclass_params__', '__dataclass_fields__', '__init__', '__repr__', '__eq__', '__hash__'])

When I changed __post_init__ to __init__ and using super().__init__() for the inheritance, still can't the attributes from class C and lose the advantage of dataclass , ie,当我将__post_init__更改为__init__并使用super().__init__()进行继承时,仍然无法获取类C的属性并失去dataclass的优势,即,

>>> @dataclasses.dataclass
class D(A, B):
    def __init__(self):
        super().__init__()
        for _field, _field_property in C.__dataclass_fields__.items():
            if _field != "g":
                setattr(self, _field, _field_property.default)

And run并运行

>>> d = D(a=4, b=2, c=5, d=3.4, e=2.1, g=55)
Traceback (most recent call last):
  File "<pyshell#81>", line 1, in <module>
    d = D(a=4, b=2, c=5, d=3.4, e=2.1, g=55)
TypeError: __init__() got an unexpected keyword argument 'a'

What should I do?我该怎么办?

Similar as what proposed by @GiacomoAlzetta, I suddenly come out that idea using dataclasses.make_dataclass , ie, generate a copy of C but excluding attribute g , ie,如什么建议@GiacomoAlzetta类似,我突然用出来这个想法dataclasses.make_dataclass ,即生成的副本C但不包括属性g ,即

<<< C_part = dataclasses.make_dataclass("C_part", [(_field, _field_property.type, _field_property.default) for _field, _field_property in C.__dataclass_fields__.items() if _field != "g"])

Thus I have因此我有

>>> C_part.__dataclass_fields__.keys()  # dict_keys(['e', 'f'])

Then the D can be obtained by那么D可以通过

>>> @dataclasses.dataclass
class D(A, B, C_part):
    pass

>>> d = D(a=4, b=2, c=5, d=3.4, e=2.1, f=55)
>>> d
D(e=2.1, f=55, d=3.4, b=2, a=4, c=5)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM