0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

分享一个最新的的Python对象序列化方式

马哥Linux运维 来源:Hynek Schlawack 作者:Hynek Schlawack 2021-09-01 15:19 次阅读

许多Python标准库都有一些未被赏识的精华。其中之一是允许简单优雅的基于参数类型的函数分发。这一特性对于任意对象的序列化而言是非常完美的——例如对于web API的JSON或结构化日志而言。

谁应该都见过这个:

9b2e5f14-0acf-11ec-911a-12bb97331649.png

虽然这不是什么大问题。json模块(API继承自simplejson)提供了两种方式来序列化对象:

1. 实现一个default()函数,它接收一个对象作为参数并且返回可以被JSONEncoder理解的东西;

2. 你自己实现或子类化一个JSONEncoder,并且把它作为cls传递给dump方法。你可以自己实现它或者简单地重写JSONEncoder.default()方法。

由于一些第三方的实现希望能够被大多数程序兼容,所以他们都不同程度的模仿了json模块的API1。

扩展性

所有上述方法的共性是它们不具有扩展性:不提供对新类型的支持。你的default()函数需要知道所有你想要序列化的自定义类型。这意味着你或者像这样写你的函数:

9b3d44ac-0acf-11ec-911a-12bb97331649.jpg

这看起来非常痛苦,因为你需要在一个地方为所有不同类型对象增加序列化结果2。

或者另一种方法,你可以自己尝试提出一种一般性的解决方案,就像Pyramid的JSON渲染器在JSON.add_adapter中做的一样,它使用了被广泛低估的zope.interface的适配器注册表3。

另一方面,Django自己实现了一个DjangoJSONEncoder,它是json.JSONEncoder的子类,它知道如何去编码日期,时间,UUID和premise等。但是除此之外,你又需要依靠自己了。如果你想深入研究Django和web API,那么你可能已经准备好使用Django的REST框架了。它们实现了一整套序列化系统,它比仅仅让数据进行json.dump()做了更多的工作。

最后,为了完整性,我感觉我不得不提到我自己在我第一天开始就极其讨厌的structlog中的解决方案:为你的类增加一个__structlog__方法,它会像__str__一样返回一个序列化后的表示方法。请不要重复我的错误。标签:software clown。

JSON已经很流行了,然而很奇怪的是我们对于序列化的解决方案却仍旧不够完善。我个人想要的是能够注册一个中心化的序列化工具,但是却以一个去中心化的方式来使用,这样可以不需要对我的类(或者更糟的,第三方类)进行任何修改。

进入PEP443

Python3.4以PEP 443的形式给出了对这个问题的一个好的解决方案:functools.singledispatch(老式Python版本也可以在PyPI上找到)。

简单说,你可以定义一个默认的函数然后根据第一个参数的类型注册一个该函数的额外版本:

9b57351a-0acf-11ec-911a-12bb97331649.jpg

现在你也可以对datetime实例调用to_serializable()方法,singledispatch会选择正确的函数

9b634044-0acf-11ec-911a-12bb97331649.png

这一方法让你能够把你的序列化器放在任何你想放的位置:放在类里,在一个独立的模块里,或者放在JSON相关的代码里。你自己选!但是你的类要保持干净,并且你不需要巨大的繁琐的if-elif-else分支。

更深入一点

显然,@singledispatch的使用比JSON更加深入。一般而言,为不同类型的对象绑定不同的行为以及独立的序列化方式是普遍适用的4。我的一些校对员提到了他们尝试了采用字典类近似替代可调用对象以及其他一些类似的“残暴的”做法。

换句话说,@singledispatch就是一个长久以来就存在的但是却被你忽略的函数。

P.S. 当然,PyPI中也有一个*multiple*dispatch。

脚注

1. 然而,对于非常出名的一个:UltraJSON一点都不支持自定义对象的序列化,此外,python-rapidjson仅仅支持default()函数。

2. 利用attrs是可以很好管理的!也许你应当使用attrs!

3. 不幸的是Pyramid使用的API自从zope.component移植过来之后还没有形成文档。

4. 我听说将singlepatch加进标准库的最原始动力来自于对pprint的一个更优雅的实现(虽然从来没有实现过)

原文链接:https://hynek.me/articles/serialization/

(版权归原作者所有,侵删)

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • API
    API
    +关注

    关注

    2

    文章

    1379

    浏览量

    60982
  • 函数
    +关注

    关注

    3

    文章

    3861

    浏览量

    61303
  • 代码
    +关注

    关注

    30

    文章

    4554

    浏览量

    66720
  • python
    +关注

    关注

    51

    文章

    4669

    浏览量

    83456
  • JSON
    +关注

    关注

    0

    文章

    111

    浏览量

    6813

原文标题:更好的Python对象序列化方式

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    鸿蒙原生应用开发-ArkTS语言基础类库多线程并发概述

    可以通过递归的方式拷贝传输对象,相较于其他序列化的算法,支持的对象类型更加丰富。 序列化支持的类型包括:除Symbol之外的基础类型、Dat
    发表于 03-28 14:35

    俄勒冈州禁止数码设备使用“序列化”技术

    该法案对诸如苹果iPhone等数字产品产生巨大影响,意即制造商无法利用“零件序列化”技术束缚消费者选择第三方维修服务或自主修复非原产部件,同时也不能以此减少设备性能或误导使用者。
    的头像 发表于 03-28 10:46 272次阅读

    鸿蒙原生应用开发-ArkTS语言基础类库多线程并发概述

    可以通过递归的方式拷贝传输对象,相较于其他序列化的算法,支持的对象类型更加丰富。 序列化支持的类型包括:除Symbol之外的基础类型、Dat
    发表于 03-22 15:40

    什么时候需要Boost序列化

    () const { return m_strName;} private :std::string m_strName;}; 然后我们想把这个类的一个对象保存到文件中或者通过网络发出去,怎么办呢?答案就是:把这个对象序列化
    的头像 发表于 11-10 10:14 198次阅读

    protobuf的编码和存储方式

    中 收发两端进行消息交互。所谓的“结构数据”是指类似于struct结构体的数据,可用于表示一个网络消息。当结构体中存在函数指针类型时,直接对其存储或传输相当于是“浅拷贝”,而对其序列化后则是“深拷贝”。) 序列化:将结构数据或者对象
    的头像 发表于 11-09 09:27 438次阅读
    protobuf的编码和存储<b class='flag-5'>方式</b>

    Java序列化怎么使用

    转换方式就叫做序列化。将文件或者网络传输中得到的 byte[] 数组转换为 java 对象就叫做反序列化。 怎么使用 如果一个 Java 对象
    的头像 发表于 10-10 14:19 244次阅读

    Spring Boot时配置JSON序列化选项的几种方法

    在Spring Boot Web 项目中,当使用JSON格式接收数据和返回数据的时候,Spring Boot 默认使用一个ObjectMapper实例来序列化响应和反序列化请求。 在本文中,我们
    的头像 发表于 10-09 10:26 1242次阅读

    如何用C语言进行json的序列化和反序列化

    json是目前最为流行的文本数据传输格式,特别是在网络通信上广泛应用,随着物联网的兴起,在嵌入式设备上,也需要开始使用json进行数据传输,那么,如何快速简洁地用C语言进行json的序列化和反序列化
    的头像 发表于 10-07 11:05 830次阅读

    如何使用Serde进行序列化和反序列化

    Serde 是一个用于序列化和反序列化 Rust 数据结构的库。它支持 JSON、BSON、YAML 等多种格式,并且可以自定义序列化和反序列化方式
    的头像 发表于 09-30 17:09 852次阅读

    ROS中的序列化实现

    理解了序列化,再回到ROS。我们发现,ROS没有采用第三方的序列化工具,而是选择自己实现,代码在roscpp_core项目下的roscpp_serialization中,见下图。这个功能涉及的代码
    的头像 发表于 09-14 17:26 591次阅读

    什么是序列化 为什么要序列化

    什么是序列化? “序列化”(Serialization )的意思是将一个对象转化为字节流。 这里说的对象可以理解为“面向对象”里的那个
    的头像 发表于 09-14 17:22 1499次阅读
    什么是<b class='flag-5'>序列化</b> 为什么要<b class='flag-5'>序列化</b>

    基于反序列化过采样数据的时钟和数据恢复单元

    电子发烧友网站提供《基于反序列化过采样数据的时钟和数据恢复单元.pdf》资料免费下载
    发表于 09-13 10:41 0次下载
    基于反<b class='flag-5'>序列化</b>过采样数据的时钟和数据恢复单元

    Python的面向对象编程详解

    一般编程可分为面向过程编程,和面向对象编程。Python的面向对象编程,与Java的面向对象很像。之所以需要面向对象编程,是为了更好地实现封
    发表于 09-04 16:35 266次阅读
    <b class='flag-5'>Python</b>的面向<b class='flag-5'>对象</b>编程详解

    蚂蚁集团开源高性能多语言序列化框架Fury解读

    Fury 是一个基于 JIT 动态编译和零拷贝的多语言序列化框架,支持 Java/Python/Golang/JavaScript/C++ 等语言,提供全自动的对象多语言 / 跨语言序列化
    的头像 发表于 08-25 17:05 734次阅读
    蚂蚁集团开源高性能多语言<b class='flag-5'>序列化</b>框架Fury解读

    Python面向对象深化(下)

    __call__  方法和可调用对象 凡是可以将 () 直接应用到自身并执行, 都称为可调用对象. 注意: 可调用对象包括自定义的函数、Python 内置函数、以及本节所讲的实例
    的头像 发表于 05-11 17:52 468次阅读