如何使用 Python 模块“attrs”实现“attr.asdict(MyObject)”的逆向

Posted

技术标签:

【中文标题】如何使用 Python 模块“attrs”实现“attr.asdict(MyObject)”的逆向【英文标题】:How to achieve the reverse of "attr.asdict(MyObject)" using Python module 'attrs' 【发布时间】:2017-12-01 18:50:36 【问题描述】:

在Python模块attrsstated的documentation中,有一种方法可以将属性的类转换为字典表示:

示例:

>>> @attr.s
... class Coordinates(object):
...     x = attr.ib()
...     y = attr.ib()
...
>>> attr.asdict(Coordinates(x=1, y=2))
'x': 1, 'y': 2

我怎样才能达到相反的效果:从其有效的字典表示中获取Coordinates 的实例,而无需样板文件,并享受attrs 模块的乐趣?

【问题讨论】:

【参考方案1】:

作为一种更通用的解决方案,它适用于 attrs 嵌套类、枚举或任何其他类型的注释结构,您可以使用 https://github.com/Tinche/cattrs

例子:

import attr, cattr

@attr.s(slots=True, frozen=True)  # It works with normal classes too.
class C:
        a = attr.ib()
        b = attr.ib()

instance = C(1, 'a')
cattr.unstructure(instance)
# 'a': 1, 'b': 'a'
cattr.structure('a': 1, 'b': 'a', C)
# C(a=1, b='a')

【讨论】:

【参考方案2】:

显然就像在对应的 attrs 类实例化中使用字典解包 (double star) 运算符一样简单。

示例:

>>> Coordinates(**'x': 1, 'y': 2)
Coordinates(x=1, y=2)

【讨论】:

这只有在你的类是扁平的并且没有嵌套的复杂类型时才有效。【参考方案3】:

我在我的网络应用程序中执行此操作,以便能够序列化/反序列化为 JSON:

首先,我在我的类上创建了一个方法,该方法返回一个对序列化更友好的版本:

def asdict(self, serializable=True):
    if serializable:
        as_dict['type'] = self.__class__.__name__
        return as_dict
    else:
        return attr.asdict(self)

然后当我需要将这些字典之一(实际上是 JSON 对象)转换回类实例时:

obj_type = values.pop('type')
if obj_type in obj_list:
    obj = getattr(sys.modules[__name__], obj_type)(**values)

【讨论】:

据我了解,您的解决方案需要一个带有类型名称的附加状态?此外,不清楚您所说的“我在我的类上创建了一个方法”指的是哪些类。无论哪种方式,我只收到我无法修改的 python 字典,但可以期望具体的键将其建模为简单的 DTO,以便进一步使用。 另外,@patrick-shechetin 您可以使用通用方法从 JSON 字典中动态创建 attrs DTO。更重要的是,如果你有他们的 JSON 模式,你不需要在有效负载本身中携带类型名称。只要您可以确保您的字典针对具体类型的模式进行验证。您可以在我的其他 Q/A 中找到更多关于 JSLattrs 的信息。

以上是关于如何使用 Python 模块“attrs”实现“attr.asdict(MyObject)”的逆向的主要内容,如果未能解决你的问题,请参考以下文章

python学习——Beautifulsoup 模块

$attrs和$listeners

继承ViewGroup自定义View:步骤attrs.xmlTypedArray

vue $attrs、$listeners使用

使用 attrs 将 JSON 转换为 Python 类

Python 模块