从其他数据类实例填充数据类实例
populate dataclass instance from other dataclass instance
我有两个数据class,它们共享一些命令键。比方说
@dataclass
class A
key1: str = ""
key2: dict = {}
key3: Any = ""
和classB
@dataclass
class B
key1: str = ""
key3: Any = ""
key4: List = []
这两个 class 共享一些键值。现在我想将 class A 中的公共键值分配给 class B 实例。
我知道的一种方法是将 class 转换为 dict
对象,然后将其转换回数据class 对象。但据我所知, dataclass 的唯一目的是有效地存储数据和管理。我相信有一些更好的方法。
预期的输入和输出
# State of dataclass A while B is not initialized
A(key1: "key1value", Key2: {"a": "a"}, key3: [1,2])
# State of B should be
B(key1: "key1value",key3: [1,2], key4: [])
您可以使用signature
获取您的class的所有属性,然后getattr
检查键是否同名,最后setattr
更改classB
的值,像这样:
from dataclasses import dataclass, field
from inspect import signature
from typing import Any, List, Dict
def main():
instanceA, instanceB = A("key1value", {"a": "a"}, [1,2]), B()
attrsA, attrsB = signature(A).parameters, signature(B).parameters
for attr in attrsA:
if attr in attrsB:
valueA = getattr(instanceA, attr)
setattr(instanceB, attr, valueA)
@dataclass
class A:
key1: str = ""
key2: Dict[str, str] = field(default_factory=dict)
key3: Any = ""
@dataclass
class B:
key1: str = ""
key3: Any = ""
key4: List = field(default_factory=list)
if __name__ == '__main__':
main()
分配前的实例数:
A(key1='key1value', key2={'a': 'a'}, key3=[1, 2])
B(key1='', key3='', key4=[])
之后:
A(key1='key1value', key2={'a': 'a'}, key3=[1, 2])
B(key1='key1value', key3=[1, 2], key4=[])
如果您向 class 添加一个方法,您可以对任何 class 执行此操作,并将其用于 A 到 B 或 B 到 A。
我在 signature 中看到的问题是,如果您在 init 中进行任何更改,例如,对于 B,将 class A 作为参数,它将不再起作用。
from dataclasses import dataclass, field, fields
from typing import Any
@dataclass
class A:
key1: str = ""
key2: dict = field(default_factory=dict)
key3: Any = ""
def set_keys(self, other):
self_fields = list(map(lambda x: x.name, fields(self)))
for _field in fields(other):
if _field.name in self_fields:
setattr(self, _field.name, getattr(other, _field.name))
@dataclass
class B:
key1: str = ""
key3: Any = ""
key4: list = field(default_factory=list)
def set_keys(self, other):
self_fields = list(map(lambda x: x.name, fields(self)))
for _field in fields(other):
if _field.name in self_fields:
setattr(self, _field.name, getattr(other, _field.name))
a = A(key1="key1value", key3=[1, 2])
b = B()
b.set_keys(a)
结果:
A(key1='key1value', key2={'a': 'a'}, key3=[1, 2])
B(key1='key1value', key3=[1, 2], key4=[])
我有两个数据class,它们共享一些命令键。比方说
@dataclass
class A
key1: str = ""
key2: dict = {}
key3: Any = ""
和classB
@dataclass
class B
key1: str = ""
key3: Any = ""
key4: List = []
这两个 class 共享一些键值。现在我想将 class A 中的公共键值分配给 class B 实例。
我知道的一种方法是将 class 转换为 dict
对象,然后将其转换回数据class 对象。但据我所知, dataclass 的唯一目的是有效地存储数据和管理。我相信有一些更好的方法。
预期的输入和输出
# State of dataclass A while B is not initialized
A(key1: "key1value", Key2: {"a": "a"}, key3: [1,2])
# State of B should be
B(key1: "key1value",key3: [1,2], key4: [])
您可以使用signature
获取您的class的所有属性,然后getattr
检查键是否同名,最后setattr
更改classB
的值,像这样:
from dataclasses import dataclass, field
from inspect import signature
from typing import Any, List, Dict
def main():
instanceA, instanceB = A("key1value", {"a": "a"}, [1,2]), B()
attrsA, attrsB = signature(A).parameters, signature(B).parameters
for attr in attrsA:
if attr in attrsB:
valueA = getattr(instanceA, attr)
setattr(instanceB, attr, valueA)
@dataclass
class A:
key1: str = ""
key2: Dict[str, str] = field(default_factory=dict)
key3: Any = ""
@dataclass
class B:
key1: str = ""
key3: Any = ""
key4: List = field(default_factory=list)
if __name__ == '__main__':
main()
分配前的实例数:
A(key1='key1value', key2={'a': 'a'}, key3=[1, 2])
B(key1='', key3='', key4=[])
之后:
A(key1='key1value', key2={'a': 'a'}, key3=[1, 2])
B(key1='key1value', key3=[1, 2], key4=[])
如果您向 class 添加一个方法,您可以对任何 class 执行此操作,并将其用于 A 到 B 或 B 到 A。
我在 signature 中看到的问题是,如果您在 init 中进行任何更改,例如,对于 B,将 class A 作为参数,它将不再起作用。
from dataclasses import dataclass, field, fields
from typing import Any
@dataclass
class A:
key1: str = ""
key2: dict = field(default_factory=dict)
key3: Any = ""
def set_keys(self, other):
self_fields = list(map(lambda x: x.name, fields(self)))
for _field in fields(other):
if _field.name in self_fields:
setattr(self, _field.name, getattr(other, _field.name))
@dataclass
class B:
key1: str = ""
key3: Any = ""
key4: list = field(default_factory=list)
def set_keys(self, other):
self_fields = list(map(lambda x: x.name, fields(self)))
for _field in fields(other):
if _field.name in self_fields:
setattr(self, _field.name, getattr(other, _field.name))
a = A(key1="key1value", key3=[1, 2])
b = B()
b.set_keys(a)
结果:
A(key1='key1value', key2={'a': 'a'}, key3=[1, 2])
B(key1='key1value', key3=[1, 2], key4=[])