dataclass 可以继承普通 Python class 的属性吗?
Can a dataclass inherit attributes from a normal Python class?
我有一个遗留物 class,它被用作数据结构。它包含一些属性和一些方法(如过去使用的 from_dict()
和 to_dict()
)。 class 还从另一个普通基础 class.
继承了一些属性
我希望将所有这些属性移动到一个新的 @dataclass
中。我的新 dataclass
可以从现有的普通 class 继承所有这些旧属性吗?但显然不是方法。
我想实现类似的东西:
from dataclasses import dataclass
class BaseClass1:
def __init__(
self,
id: int,
type: str,
):
self.id = id
self.type = type
def to_dict(self):
# Dummy code here
pass
def from_dict(self):
# Dummy code here
pass
class BaseClass2(BaseClass1):
def __init__(self, speed: float, **kwargs):
self.speed = speed
super().__init__(**kwargs)
def to_dict(self):
# Dummy code here
pass
def from_dict(self):
# Dummy code here
pass
@dataclass
class NewDataStructure(BaseClass2):
color: str
owner: str
if __name__ == "__main__":
new_data = NewDataStructure(
color="red", owner="john", speed=23.7, id=345, type="car"
)
print(new_data)
我会在这里使用多重继承,最终 class 从数据 class 和普通基础 class 继承。这样您就可以将初始化转发给基础 __init__
方法,任何进一步的更改都将自动包含在内。
根据你的例子,我会使用:
@dataclass
class TmpDataStructure():
color: str
owner: str
class NewDataStructure(TmpDataStructure, BaseClass2):
def __init__(self, **kwargs):
super().__init__(**{k: v for k, v in kwargs.items()
if k in TmpDataStructure.__match_args__})
BaseClass2.__init__(self, **{k: v for k, v in kwargs.items()
if k not in TmpDataStructure.__match_args__})
您将能够安全地做到:
new_data = NewDataStructure(
color="red", owner="john", speed=23.7, id=345, type="car"
)
print(new_data)
但是你只会得到数据中定义的字段class:
NewDataStructure(color='red', owner='john')
这也将继承 BaseClass2
和 BaseClass1
的方法...
假设所有常规 类 中 __init__
的函数参数对每个参数都有一个类型注释 - 例如 id: int
- 那么下面的方法或修改版本它应该有望在您的情况下起作用,以生成一个近似的数据类模式,给定任意数量的常规 类,sub-class 来自另一个:
from dataclasses import dataclass, fields
class BaseClass1:
def __init__(
self,
id: int,
type: str,
):
self.id = id
self.type = type
def to_dict(self):
# Dummy code here
pass
def from_dict(self):
# Dummy code here
pass
class BaseClass2(BaseClass1):
def __init__(self, speed: float, **kwargs):
self.speed = speed
super().__init__(**kwargs)
def to_dict(self):
# Dummy code here
pass
def from_dict(self):
# Dummy code here
pass
@dataclass
class NewDataStructure(BaseClass2):
color: str
owner: str
dataclass_fields = []
# start from 1: exclude `NewDataStructure` itself
# exclude last at -1: base for all types is `object`
for cls in reversed(NewDataStructure.__mro__[1:-1]):
init_fn_annotated_params = getattr(cls.__init__, '__annotations__', {})
if not init_fn_annotated_params:
continue
dataclass_fields.append(f' # generated from `{cls.__qualname__}`')
for field, ftype in init_fn_annotated_params.items():
type_name = getattr(ftype, '__qualname__', ftype.__name__)
dataclass_fields.append(f' {field}: {type_name}')
# now finally, print out the generated dataclass schema
print('@dataclass')
print('class NewDataStructure(BaseClass2):')
print('\n'.join(dataclass_fields))
print(' # generated from `NewDataStructure`')
for f in fields(NewDataStructure):
type_name = getattr(f.type, '__qualname__', f.type.__name__)
print(f' {f.name}: {type_name}')
输出:
@dataclass
class NewDataStructure(BaseClass2):
# generated from `BaseClass1`
id: int
type: str
# generated from `BaseClass2`
speed: float
# generated from `NewDataStructure`
color: str
owner: str
我有一个遗留物 class,它被用作数据结构。它包含一些属性和一些方法(如过去使用的 from_dict()
和 to_dict()
)。 class 还从另一个普通基础 class.
我希望将所有这些属性移动到一个新的 @dataclass
中。我的新 dataclass
可以从现有的普通 class 继承所有这些旧属性吗?但显然不是方法。
我想实现类似的东西:
from dataclasses import dataclass
class BaseClass1:
def __init__(
self,
id: int,
type: str,
):
self.id = id
self.type = type
def to_dict(self):
# Dummy code here
pass
def from_dict(self):
# Dummy code here
pass
class BaseClass2(BaseClass1):
def __init__(self, speed: float, **kwargs):
self.speed = speed
super().__init__(**kwargs)
def to_dict(self):
# Dummy code here
pass
def from_dict(self):
# Dummy code here
pass
@dataclass
class NewDataStructure(BaseClass2):
color: str
owner: str
if __name__ == "__main__":
new_data = NewDataStructure(
color="red", owner="john", speed=23.7, id=345, type="car"
)
print(new_data)
我会在这里使用多重继承,最终 class 从数据 class 和普通基础 class 继承。这样您就可以将初始化转发给基础 __init__
方法,任何进一步的更改都将自动包含在内。
根据你的例子,我会使用:
@dataclass
class TmpDataStructure():
color: str
owner: str
class NewDataStructure(TmpDataStructure, BaseClass2):
def __init__(self, **kwargs):
super().__init__(**{k: v for k, v in kwargs.items()
if k in TmpDataStructure.__match_args__})
BaseClass2.__init__(self, **{k: v for k, v in kwargs.items()
if k not in TmpDataStructure.__match_args__})
您将能够安全地做到:
new_data = NewDataStructure(
color="red", owner="john", speed=23.7, id=345, type="car"
)
print(new_data)
但是你只会得到数据中定义的字段class:
NewDataStructure(color='red', owner='john')
这也将继承 BaseClass2
和 BaseClass1
的方法...
假设所有常规 类 中 __init__
的函数参数对每个参数都有一个类型注释 - 例如 id: int
- 那么下面的方法或修改版本它应该有望在您的情况下起作用,以生成一个近似的数据类模式,给定任意数量的常规 类,sub-class 来自另一个:
from dataclasses import dataclass, fields
class BaseClass1:
def __init__(
self,
id: int,
type: str,
):
self.id = id
self.type = type
def to_dict(self):
# Dummy code here
pass
def from_dict(self):
# Dummy code here
pass
class BaseClass2(BaseClass1):
def __init__(self, speed: float, **kwargs):
self.speed = speed
super().__init__(**kwargs)
def to_dict(self):
# Dummy code here
pass
def from_dict(self):
# Dummy code here
pass
@dataclass
class NewDataStructure(BaseClass2):
color: str
owner: str
dataclass_fields = []
# start from 1: exclude `NewDataStructure` itself
# exclude last at -1: base for all types is `object`
for cls in reversed(NewDataStructure.__mro__[1:-1]):
init_fn_annotated_params = getattr(cls.__init__, '__annotations__', {})
if not init_fn_annotated_params:
continue
dataclass_fields.append(f' # generated from `{cls.__qualname__}`')
for field, ftype in init_fn_annotated_params.items():
type_name = getattr(ftype, '__qualname__', ftype.__name__)
dataclass_fields.append(f' {field}: {type_name}')
# now finally, print out the generated dataclass schema
print('@dataclass')
print('class NewDataStructure(BaseClass2):')
print('\n'.join(dataclass_fields))
print(' # generated from `NewDataStructure`')
for f in fields(NewDataStructure):
type_name = getattr(f.type, '__qualname__', f.type.__name__)
print(f' {f.name}: {type_name}')
输出:
@dataclass
class NewDataStructure(BaseClass2):
# generated from `BaseClass1`
id: int
type: str
# generated from `BaseClass2`
speed: float
# generated from `NewDataStructure`
color: str
owner: str