I constructed multiple base 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. 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. Checking the child class 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, i.e.,
>>> @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?
dataclassesreally supports inheritance.C'that is likeCwithout thegattribute,Cbecomes a subclass ofC'adding the newgattribute, and yourDinheritsA,B, C'. Dataclasses work at class creation time,__post_init__works at instance creation time, i.e. way too late to modify the definition of__init__Dmight be better off having instances ofA,B, and maybeC_partinstead of inheriting them.