Я построил множественную базу dataclass
. Теперь я хочу создать дочерний dataclass
, унаследованный от этих базовых классов, но может унаследовать часть атрибутов, определенных в некоторых базовых классах. Примеры могут быть:
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)
А именно, я хочу создать дочерний класс D
, наследующий A
и B
, а также атрибуты в C
, кроме g
. Проверка дочернего класса 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'
А также
>>> D.__dict__.keys()
dict_keys(['__module__', '__post_init__', '__doc__', '__dataclass_params__', '__dataclass_fields__', '__init__', '__repr__', '__eq__', '__hash__'])
Когда я изменил __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)
И беги
>>> 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'
Что я должен делать?
dataclasses
действительно поддерживает наследование. - person AKX   schedule 09.03.2020C'
, который похож наC
без атрибутаg
,C
станет подклассомC'
, добавив новый атрибутg
, а вашD
наследуетA,B, C'
. Классы данных работают в время создания класса,__post_init__
работают в время создания экземпляра, т.е. слишком поздно для изменения определения__init__
- person Giacomo Alzetta   schedule 09.03.2020D
может быть лучше иметь экземплярыA
,B
и, возможно,C_part
вместо их наследования. - person Arne   schedule 09.03.2020