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

    文章

    2469

    浏览量

    66998
  • 函数
    +关注

    关注

    3

    文章

    4421

    浏览量

    67822
  • 代码
    +关注

    关注

    30

    文章

    4976

    浏览量

    74359
  • python
    +关注

    关注

    58

    文章

    4883

    浏览量

    90295
  • JSON
    +关注

    关注

    0

    文章

    129

    浏览量

    7808

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

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

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    JSON:简洁代码高效搞定序列化与反序列化

    面对频繁的数据交互需求,用最简方式实现JSON序列化与反序列化已成为开发者必备技能,借助主流库,轻松实现零负担数据转换。JSON(JavaScriptObjectNotation)是
    的头像 发表于 02-25 19:04 223次阅读
    JSON:简洁代码高效搞定<b class='flag-5'>序列化</b>与反<b class='flag-5'>序列化</b>

    IO序列化操作:提升系统互操作性的关键技术

    在异构系统并存的今天,IO序列化操作成为实现系统间互操作性的核心技术。通过标准的数据格式(如JSON、Protobuf、Hessian等),不同语言、平台的系统得以无缝交换信息。合理设计序列化策略
    的头像 发表于 02-25 16:02 188次阅读
    IO<b class='flag-5'>序列化</b>操作:提升系统互操作性的关键技术

    【ioqueue】 IO序列化操作全解析

    从内存对象到可存储或可传输的字节流,IO序列化操作完成了数据形态的转化。这过程不仅涉及编码与解码逻辑,还需处理版本兼容、安全性与性能开销等问题。全面掌握这技术路径,有助于构建更加健
    的头像 发表于 02-24 19:22 203次阅读
    【ioqueue】 IO<b class='flag-5'>序列化</b>操作全解析

    极简代码,搞定JSON序列化与反序列化

    快速实现JSON数据的生成(序列化)与解析(反序列化)。 目前json库已全面支持LuatOS开发系列产品,开发者可根据项目实际需求,灵活选用并进行快速集成与开发。 、 JSON基础要点 在
    的头像 发表于 02-23 21:46 436次阅读
    极简代码,搞定JSON<b class='flag-5'>序列化</b>与反<b class='flag-5'>序列化</b>

    深入剖析LMH0030:SMPTE标准数字视频序列化器的卓越之选

    深入剖析LMH0030:SMPTE标准数字视频序列化器的卓越之选 在当今数字的时代,数字视频处理技术日新月异。对于电子工程师而言,选择款性能卓越、功能丰富的数字视频序列化器至关重要
    的头像 发表于 12-30 14:00 417次阅读

    深入解析LM2512A:高性能RGB显示接口序列化

    深入解析LM2512A:高性能RGB显示接口序列化器 在电子设备的显示领域,如何高效、稳定地传输高质量的图像数据是关键问题。TI的LM2512A作为款专门的移动像素链路(MPL
    的头像 发表于 12-26 11:30 566次阅读

    SN65HVS885:工业自动的理想数字输入序列化

    SN65HVS885:工业自动的理想数字输入序列化器 在工业和建筑自动领域,对于高通道密度数字输入模块的需求日益增长。德州仪器(TI)的SN65HVS885作为款八通道数字输入
    的头像 发表于 12-25 11:00 573次阅读

    深度解析DS90UH929-Q1:720p HDMI 到 FPD-Link III 桥接序列化

    深度解析DS90UH929-Q1:720p HDMI 到 FPD-Link III 桥接序列化器 在电子工程师的日常工作中,选择款合适的器件来实现特定功能至关重要。今天,我们聚焦于德州仪器(TI
    的头像 发表于 12-22 15:50 540次阅读

    DS90UH947-Q1:1080p OpenLDI至FPD - Link III序列化器的深度解析

    迫切。DS90UH947 - Q1 作为款专为汽车应用等场景打造的 1080p OpenLDI 至 FPD - Link III 序列化器,凭借其卓越的性能和丰富的功能,在市场上占据了重要的
    的头像 发表于 12-22 15:40 472次阅读

    探索DS90UH981-Q1:4K DSI到FPD-Link IV桥接序列化器的卓越性能

    探索DS90UH981-Q1:4K DSI到FPD-Link IV桥接序列化器的卓越性能 在当今的电子设备设计领域,对于高速、可靠且功能强大的视频传输解决方案的需求与日俱增。DS90UH981-Q1
    的头像 发表于 12-17 11:15 636次阅读

    轻量级参数的管理框架(C语言)

    和反序列化操作。 方便在本地储存设备(如flash、eeprom等)保存/读取二进制数据,甚至还可以跨设备传输使用 提供了两种方式: 第种:只需要提供参数数据保存/加载的回调函数,调用相关接口函数
    发表于 12-16 06:24

    基础篇3:掌握Python中的条件语句与循环

    : print(\"你还很小。\") 循环 循环允许程序重复执行段代码,直到满足某个条件为止。Python中有几种不同的循环结构。 for循环 for循环通常用于遍历序列(如列表、元组
    发表于 07-03 16:13

    TaskPool和Worker的对比分析

    TaskPoolWorker内存模型线程间隔离,内存不共享。线程间隔离,内存不共享。 参数传递机制采用标准的结构克隆算法(Structured Clone)进行序列化、反序列化,完成参数传递。 支持ArrayBuffer
    发表于 06-18 06:43

    鸿蒙5开发宝藏案例分享---跨线程性能优化指南

    发现鸿蒙宝藏:跨线程序列化性能优化实战指南 大家好呀!今天在翻鸿蒙文档时挖到超级实用的工具—— DevEco Profiler的序列化检测功能 !平时用<span class
    发表于 06-12 17:13

    快手上线鸿蒙应用高性能解决方案:数据反序列化性能提升90%

    普通对象(如 JSON 数据)与类实例进行互转,是实现面向对象编程与数据序列化解耦的核心工具。随着业务复杂度的提升,该库在反序列化过程中逐渐暴露出性能瓶颈,影响用户核心体验。因此
    发表于 05-15 10:01