迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > Python >

python 如何将字典转换为数据类

作者:迹忆客 最近更新:2023/04/25 浏览次数:

本文的主要目的是演示如何将嵌套字典转换为数据类。 介绍了三种不同类型的方法及其解释。


将字典转换回数据类

根据您正在进行的项目,您可能会遇到需要将字典转换回数据类的场景。 虽然这种情况可能很少见,但在某些情况下您可能需要进行转换,尤其是当您想要防止意外行为时。

这种情况的一个示例是转换后的字典是嵌套的或复杂的,例如具有复杂类型的成员或数据类的成员。

从数据类导入数据类,asdict

@dataclass
class A:
    x: int

@dataclass
class B:
    x: A
    y: A

@dataclass
class C:
    a: B
    b: B

在上述情况下,数据类 C 在转换为字典时有时会造成转换问题。 问题的发生主要是由于类成员类型的处理失败。

要克服此解决方案,您可以根据自己的喜好和项目的性质选择多种方法。 如果您正在从事个人项目并且对数据性质的范围有很好的了解,那么使用简单的变通方法是安全的。

但是,在大规模数据的情况下,通常建议安全起见并使用第三方库(最好是开源的),因为它们是为在广泛的用例上运行而设计的。 因此,它允许他们处理更广泛的数据变体。


使用 post_init 将字典转换回数据类

最简单的方法之一是利用在初始化数据类后自动调用的 __post_init__ 函数。

从数据类导入数据类,asdict

@dataclass
class SimpleDClazz:
    m_one: str
    m_two: str

@dataclass
class ComplexDClazz:
    simpKlazz: SimpleDClazz

    def __post_init__(self):
        if isinstance(self.simpKlazz, dict):
            self.simpKlazz = SimpleDClazz(**self.simpKlazz)

foo = ComplexDClazz(simpKlazz=SimpleDClazz(m_one="1", m_two="2"))

d= asdict(foo)
print(d)
o = ComplexDClazz(**d)
print(o)

输出:

{'simpKlazz': {'m_one': '1', 'm_two': '2'}}
ComplexDClazz(simpKlazz=SimpleDClazz(m_one='1', m_two='2'))

初始化数据类 ComplexDClazz 后调用 _post_init 函数。 由于这个独特的属性,我们可以使用它来帮助将字典转换回数据类。

所有必要的实现都在 __post_init_ 函数中完成。 代码可以分为两个主要部分:

  1. 在函数的开始,判断传入的字典dict是否与我们成员simpKlazz的类型相同。
  2. 如果条件为真,则在将字典值转换为正确类型后更新成员变量 simpKlazz。

使用适宜性

尽管体积小且独立,但即使在对不同类型的数据类进行严格测试后,该解决方案仍能保持良好状态。 如果您正在寻找一个独立的小型解决方案,这个解决方案似乎是一个不错的选择,但您可能必须在您计划使用的每个数据类中实现这个功能。

如果您正在从事大型项目,请将您自己的测试用例应用到解决方案中,看看它是否适合您的用例。


使用自定义实现将字典转换回数据类

考虑以下用于将嵌套字典转换回数据类的函数。

import dataclasses as dc
from dataclasses import dataclass, asdict

def dict_to_dataklass(klass, d):
    try:
        fieldtypes = {f.name:f.type for f in dc.fields(klass)}
        return klass(**{f:dict_to_dataklass(fieldtypes[f],d[f]) for f in d})
    except:
        return d # The object is not a dataclass field


@dataclass
class SimpleDClazz:
    x: float
    y: float

@dataclass
class ComplexDClazz:
    a: SimpleDClazz
    b: SimpleDClazz

line = ComplexDClazz(SimpleDClazz(1,2), SimpleDClazz(3,4))
assert line == dict_to_dataklass(ComplexDClazz, asdict(line))
print("Success")

输出:

Success

这个简单的五行代码包含一个 try-catch 块,其中完成了两件事:

  1. 假设 klass 是一个数据类。 提取数据类中的所有字段,它们的名称和类型更具体。
  2. 检索完所有字段后,将根据检索到的字段生成一个 klass 类型的数据类对象。 递归调用确保相应地处理和转换字段内的任何嵌套类。
  3. 当 try 块失败时(主要是当传递的参数不是所需的类型时),返回原始传递的对象。 这确保如果传递的对象不是合适的类型,它会被返回,作为递归调用的停止条件。

使用适宜性

此方法最适用于不同类型范围不大且大多数情况已知的小型项目。 对于规模较大的项目,这种方法在遇到 corner case 时可能会出乎意料地奏效。

建议使用数据类格式的测试用例对此进行测试,以根除任何潜在的错误。


使用 dacite(第三方库)将字典转换回数据类

dacite 是一个开源的第三方库,旨在简化 Python 中数据类的创建。 幸运的是,该库包含执行我们想要的功能的函数,从传递的字典(嵌套或非嵌套)创建数据类。

from dataclasses import dataclass
from dacite import from_dict

@dataclass
class DKlazz:
    m_one: str
    m_two: int
    is_working: bool

sample = {
    'm_one': '1',
    'm_two': 2,
    'is_working': False,
}

dk = from_dict(data_class=DKlazz, data=sample)

assert dk == DKlazz(m_one='1', m_two=2, is_working=False)
print("Success")

输出:

Success

dacite 仅包含一个函数,from_dict,它允许从给定的字典对象创建数据类。

使用该功能非常简单。 它由两个参数组成:数据类和字典。

然后该函数将给定的字典转换为给定类型的数据类对象并返回——所有这些都没有任何自定义函数的麻烦。

使用适宜性

开源的好处是万一遇到任何错误,会立即报告,并立即开始修复工作。 请记住,这种方法是全方位的,适用于小型和大型项目。

如果发现此类情况,可以将它们报告给 GitHub 存储库,开发人员或其他社区成员可以在其中帮助生成修复程序。 但是,如果您不想下载任何额外的第三方库,这个选项似乎不是最可行的。

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

Django 中的 Slug

发布时间:2023/05/04 浏览次数:173 分类:Python

本篇文章旨在定义一个 slug 以及我们如何使用 slug 字段在 Python 中使用 Django 获得独特的帖子。

Django ALLOWED_HOSTS 介绍

发布时间:2023/05/04 浏览次数:181 分类:Python

本文展示了如何创建您的 Django 网站,为公开发布做好准备,如何设置 ALLOWED_HOSTS 以及如何在使用 Django 进行 Web 部署期间修复预期的主要问题。

Django 中的 Select_related 方法

发布时间:2023/05/04 浏览次数:129 分类:Python

本文介绍了什么是查询集,如何处理这些查询以及我们如何利用 select_related() 方法来过滤 Django 中相关模型的查询。

在 Django 中上传媒体文件

发布时间:2023/05/04 浏览次数:198 分类:Python

在本文中,我们简要介绍了媒体文件以及如何在 Django 项目中操作媒体文件。

Django 返回 JSON

发布时间:2023/05/04 浏览次数:106 分类:Python

在与我们的讨论中,我们简要介绍了 JSON 格式,并讨论了如何借助 Django 中的 JsonResponse 类将数据返回为 JSON 格式。

在 Django 中创建对象

发布时间:2023/05/04 浏览次数:59 分类:Python

本文的目的是解释什么是模型以及如何使用 create() 方法创建对象,并了解如何在 Django 中使用 save() 方法。

在 Django 中为多项选择创建字段

发布时间:2023/05/04 浏览次数:75 分类:Python

在本文中,我们将着眼于为多项选择创建一个字段,并向您展示如何允许用户在 Django 中进行多项选择。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便