如何使用 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模块attrs
stated的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 中找到更多关于 JSL 和 attrs 的信息。以上是关于如何使用 Python 模块“attrs”实现“attr.asdict(MyObject)”的逆向的主要内容,如果未能解决你的问题,请参考以下文章