【问题标题】:Dictionary to dataclasses with inheritance of classes字典到具有类继承的数据类
【发布时间】:2020-05-01 11:06:06
【问题描述】:

我有以下课程

@dataclass_json
@dataclass
class Input:
    sources: List[Sources] =None
    Transformations: List[str] =None

还有:

@dataclass_json
@dataclass
class Source:
    type: str =None
    label: str =None
    path: str = None

和两个子类:

@dataclass_json
@dataclass
class Csv(Source):
    csv_path: str=None
    delimiter: str=';'

@dataclass_json
@dataclass
class Parquet(Source):
    parquet_path: str=None

现在给定字典:

parquet={type: 'Parquet', label: 'events', path: '/.../test.parquet', parquet_path: '../../result.parquet'}
csv={type: 'Csv', label: 'events', path: '/.../test.csv', csv_path: '../../result.csv', delimiter:','}
input={'sources':[csv, parquet]}

现在我想做类似的事情

Input().from_dict(input) 

带输出:

Input(sources: [Parquet(...), Csv(...)]).

这确实有效,但它只返回来自数据类 Source(类型、标签和路径)的 3 个参数的值,而不是 Csv 和 Parquet 的其他特定参数(csv_path、delimiter 和 parquet_path),它们只是给出了默认值价值。这可能是由于库 dataclass_json 在初始化之前采用了类的模式。另一方面,我想仍然使用 dataclass_json 并制作一个包装器,因为它具有良好的案例和错误处理能力。

我想要这种行为,因为每种源类型都有不同的参数来定义自己(例如 Csv 有分隔符,但 Parquet 没有,等等......)。

我努力尝试获取类 Source 并在库 dataclass_json 中找到子类。这样做,我遇到了

cls.__args__[0]

属于“GenericMeta”类型。但是鉴于此,我无法访问其子类。

有什么解决办法吗?

顺便说一句,我使用的是 Python 3.6。

提前感谢您的帮助。

【问题讨论】:

  • 这与您在这里的原始问题有何不同?:stackoverflow.com/questions/61339788/… 我不是专家,但我认为如果您需要澄清或添加新信息,他们宁愿您编辑原始问题,而不是问两次基本相同的问题。
  • 我稍微编辑了这个问题,使其更清晰。这里的问题主要是当我做'from dict'时它并没有采用所有值,什么是库dataclass_json中使用的方法。由于我会将其应用于 Input,因此函数 from_dict 固有地应用于 Source,因此我无法控制它。
  • 你是否试图实例化一个Input 对象,方法是向它提供如何实例化Source 子类(CsvParquet)的说明,但当它没有时你会感到失望'不这样做吗?如果是这样,那么您有 2 个选择。 1)不要那样做。首先实例化您的CsvParquet 对象,然后将它们传递给Input。 2) 咬紧牙关,实际编写一个__init__ 方法来执行此操作——或者__post_init__,如果你真的嫁给了dataclass。你不能指望它神奇地知道你想做什么。

标签: python dictionary subclass typing python-dataclasses


【解决方案1】:

我知道这个线程已经相当老了,但是对于其他正在寻找解决方案的人来说,看看 dacite。

这是他们的 github 存储库的链接:https://github.com/konradhalas/dacite#quick-start

为了完整起见,这里是快速入门代码:

from dataclasses import dataclass
from dacite import from_dict


@dataclass
class User:
    name: str
    age: int
    is_active: bool


data = {
    'name': 'John',
    'age': 30,
    'is_active': True,
}

user = from_dict(data_class=User, data=data)

assert user == User(name='John', age=30, is_active=True)

【讨论】:

    猜你喜欢
    • 2021-06-12
    • 2017-09-26
    • 2014-01-25
    • 2014-11-15
    • 1970-01-01
    • 2020-10-21
    • 2023-03-27
    • 2019-03-28
    • 2019-06-14
    相关资源
    最近更新 更多