是否可以在 python 数据类中对变量进行分组?
Posted
技术标签:
【中文标题】是否可以在 python 数据类中对变量进行分组?【英文标题】:Is it possible to group variables in a python dataclass? 【发布时间】:2021-12-02 14:10:16 【问题描述】:我已经搜索了但没有找到好的答案,所以我会发一个帖子:)
我目前正在创建一个 python 模块,它使用一个 http get 请求来获取一个具有这样结构的一堆数据的对象。
主组 第 1 组 数据1 数据2 第 2 组 数据1 数据2 第 3 组 数据1 数据2我创建了一个数据类,它只列出了所有这些变量,例如
@dataclass
class MyData:
grp1_data1: str
grp1_data2: str
grp2_data1: str
grp2_data2: str
grp3_data1: str
grp3_data2: str
@classmethod
def from_dict(cls, data: dict) -> "MyData":
return cls(
grp1_data1=data["Main group"]["Group 1"]["data1"],
grp1_data2=data["Main group"]["Group 1"]["data2"],
# And so on ...
)
我正在寻找的是一种将数据类中的变量分组的方法,类似于结构,这样我就不需要在变量名中混合组名和数据名。
我对 python 很陌生,我不知道什么样的组功能可以与数据类一起使用,如果有的话?
我希望能够写出类似grp1.data1=data["Main group"]["Group 1"]["data1"]
或类似的东西。
【问题讨论】:
制作两个数据类,一个代表一个组,另一个包含该组数据类的多个实例...? 【参考方案1】:可以使用类组合创建多级数据类来做你想做的事(可能不如 C 类型的结构优雅,但它可以工作):
@dataclass
class Top:
@dataclass
class Child:
data1: str
data2: str
Group1: Child
Group2: Child
Group3: Child
inst = Top(
Group1=Top.Child('a','b'),
Group2=Top.Child('x', 'y'),
Group3=Top.Child('101', '102')
)
# check it:
@dataclass
class Top:
@dataclass
class Child:
data1: str
data2: str
Group1: Child
Group2: Child
Group3: Child
# create an instance
inst = Top(
Group1=Top.Child('a','b'),
Group2=Top.Child('x', 'y'),
Group3=Top.Child('101', '102')
)
# check it:
assert inst.Group2.data2 == 'y'
关键是您必须将所有子成员也定义为数据类(或者更准确地说是类)。 您可以就地(如上)或单独定义子类。
【讨论】:
完美,这正是我想要的!谢谢!【参考方案2】:您的问题有点不清楚,但正如 cmets 中所建议的那样,最好将 single 模型作为代表您的组数据的数据类(即包含 data1
和data2
fields)并定义一个辅助函数,该函数构造组名到模型实例的映射,如下所示。
注意:这里假设您使用的是 Python 3.8+。对于早期版本,我会做两件事:
如果需要,请删除__future__
导入,而是从 typing
模块导入 Type
和 Dict
,因为 Python 3.8 或更早版本中的内置类型不支持下标值。
删除 Python 3.8 中引入的 walrus :=
运算符的用法,改为使用它后面的注释行。
# Future import to allow the `int | str` syntax below
# Can be removed for Python 3.10
from __future__ import annotations
from dataclasses import dataclass
from typing import TypeVar
# Create a type that can be `MyData`, or any subclass
D = TypeVar('D', bound='MyData')
@dataclass
class MyData:
data1: str
data2: str
@classmethod
def from_dict(cls: type[D], data: dict, group_num: int | str) -> D:
return cls(
data1=data['MG'][f'G group_num']['data1'],
data2=data['MG'][f'G group_num']['data2'],
)
@classmethod
def group_to_data(cls: type[D], data: dict) -> dict[int, D]:
return (group_num := int(group_key.split()[-1])): cls.from_dict(
data, group_num)
for group_key in data['MG']
# For Python 3.7 or lower, uncomment and use the below instead
# ret_dict =
# for group_key in data['MG']:
# group_num = int(group_key.split()[-1])
# ret_dict[group_num] = cls.from_dict(data, group_num)
#
# return ret_dict
测试代码:
def main():
from pprint import pprint
my_data =
'MG':
'G 1':
'data1': 'hello',
'data2': 'World!',
,
'G 2':
'data1': '',
'data2': 'Testing',
,
'G 3':
'data1': 'hello 123',
'data2': 'world 321!'
group_to_data = MyData.group_to_data(my_data)
pprint(group_to_data)
# True
assert group_to_data[1] == MyData('hello', 'World!')
输出:
1: MyData(data1='hello', data2='World!'),
2: MyData(data1='', data2='Testing'),
3: MyData(data1='hello 123', data2='world 321!')
【讨论】:
以上是关于是否可以在 python 数据类中对变量进行分组?的主要内容,如果未能解决你的问题,请参考以下文章