提问人:D.L 提问时间:10/19/2023 最后编辑:petezurichD.L 更新时间:10/20/2023 访问量:316
如何将 dict 转换为 dataclass(与 asdict 相反)?
how to convert a dict to a dataclass (reverse of asdict)?
问:
Dataclasses 模块允许用户方便地从 DataClass Reall 创建字典,如下所示:
from dataclasses import dataclass, asdict
@dataclass
class MyDataClass:
''' description of the dataclass '''
a: int
b: int
# create instance
c = MyDataClass(100, 200)
print(c)
# turn into a dict
d = asdict(c)
print(d)
但是我正在尝试执行相反的过程:dict -> dataclass。
我能做的最好的事情就是将字典解压缩回预定义的数据类中。
# is there a way to convert this dict to a dataclass ?
my_dict = {'a': 100, 'b': 200}
e = MyDataClass(**my_dict)
print(e)
我怎样才能在不必预定义数据类(如果可能)的情况下实现这一点?
答:
0赞
russhoppa
10/19/2023
#1
我会按照你所展示的去包装字典。
from dataclasses import dataclass, asdict
@dataclass
class MyDataClass:
a: int
b: int
c = MyDataClass(100, 200)
print(c)
>>> MyDataClass(a=100, b=200)
d = asdict(c)
print(d)
>>> {'a': 100, 'b': 200}
e = MyDataClass(**d)
print(e)
>>> MyDataClass(a=100, b=200)
不能将字典转换为尚不存在的数据类。在将字典转换为该类之前,必须先创建该类。如果你真的希望有一个类而不是字典,你可以使用枚举。否则,你只能通过捷径来创建类,然后将字典转换为这些类。
评论
0赞
D.L
10/20/2023
这就是我在构建问题时的想法(可能是这种情况),但实际上有 2 个很好的答案可以做到这一点......
0赞
russhoppa
10/20/2023
是的,我喜欢这些答案,但从技术上讲,它们只是“制作课程的捷径,然后将字典变成这些课程”,正如我在回答中所说的那样。
0赞
D.L
10/20/2023
我一直在寻找捷径:)。从逻辑上讲,字典的所有信息(键、值和值的类型)都可以快速映射到数据类中。因此,原生在那里是有道理的......
0赞
russhoppa
10/20/2023
明白了。是的,这是有道理的。
2赞
Seon
10/19/2023
#2
您可以使用make_dataclass
:
from dataclasses import make_dataclass
my_dict = {"a": 100, "b": 200}
make_dataclass(
"MyDynamicallyCreatedDataclass", ((k, type(v)) for k, v in my_dict.items())
)(**my_dict)
评论
0赞
D.L
10/19/2023
明。我没有发现这种方法。我总是在这里找到乐于助人的人!!make_dataclass
1赞
Jab
10/20/2023
美丽的答案!并不是说需要任何更改,而只是提供了另一种方法来做到这一点。您可以使用 zip 和 map 代替理解:make_dataclass("MyDynamicallyCreatedDataclass", zip(mydict, map(type, my_dict.values()))
0赞
D.L
10/20/2023
两个很棒的答案(我都没想到)。我将其标记为已接受的答案,因为它更接近解决方案(使数据类)。
1赞
Jab
10/19/2023
#3
可以使用 SimpleNamespace 或 namedtuple。虽然这不是一个数据类,但它是它自己的对象:
from types import SimpleNamespace
from collections import namedtuple
my_dict = {'a': 100, 'b': 200}
# SimpleNamespace solution
e = SimpleNamespace(**my_dict)
# namedtuple solution
MyClass = namedtuple("MyClass", my_dict)
f = MyClass(**my_dict)
>>> e
namespace(a=100, b=200)
>>> e.a
100
>>>
>>> MyClass
<class '__main__.MyClass'>
>>> f
MyClass(a=100, b=200)
>>> f.a
100
评论
0赞
D.L
10/19/2023
哇。2个意想不到的优秀答案。这更干净,但解决方案也很好。你有偏好吗?make_dataclass
1赞
Jab
10/20/2023
嗯,这真的要看情况。SimpleNamespace 的作用类似于字典,但允许点表示法。它;本质上是一个对象。您可以随时添加、删除和更改密钥。但实际上make_dataclass构造了一个具有具体字段的新类类型。
1赞
D.L
10/20/2023
我对此投了赞成票,因为它很优雅(并提供了使用点符号的能力)......
0赞
Jab
10/20/2023
@D.L 为了完整起见,我还提供了一个解决方案。命名元组解决方案类似于数据类解决方案,其中类具有具体字段,但在创建后无法修改collections.namedtuple
评论