0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

分享一個最新的的Python對象序列化方式

馬哥Linux運維 ? 來源:Hynek Schlawack ? 作者:Hynek Schlawack ? 2021-09-01 15:19 ? 次閱讀

許多Python標準庫都有一些未被賞識的精華。其中之一是允許簡單優(yōu)雅的基于參數(shù)類型的函數(shù)分發(fā)。這一特性對于任意對象的序列化而言是非常完美的——例如對于web API的JSON或結構化日志而言。

誰應該都見過這個:

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

雖然這不是什么大問題。json模塊(API繼承自simplejson)提供了兩種方式來序列化對象:

1. 實現(xiàn)一個default()函數(shù),它接收一個對象作為參數(shù)并且返回可以被JSONEncoder理解的東西;

2. 你自己實現(xiàn)或子類化一個JSONEncoder,并且把它作為cls傳遞給dump方法。你可以自己實現(xiàn)它或者簡單地重寫JSONEncoder.default()方法。

由于一些第三方的實現(xiàn)希望能夠被大多數(shù)程序兼容,所以他們都不同程度的模仿了json模塊的API1。

擴展性

所有上述方法的共性是它們不具有擴展性:不提供對新類型的支持。你的default()函數(shù)需要知道所有你想要序列化的自定義類型。這意味著你或者像這樣寫你的函數(shù):

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

這看起來非常痛苦,因為你需要在一個地方為所有不同類型對象增加序列化結果2。

或者另一種方法,你可以自己嘗試提出一種一般性的解決方案,就像Pyramid的JSON渲染器在JSON.add_adapter中做的一樣,它使用了被廣泛低估的zope.interface的適配器注冊表3。

另一方面,Django自己實現(xiàn)了一個DjangoJSONEncoder,它是json.JSONEncoder的子類,它知道如何去編碼日期,時間,UUID和premise等。但是除此之外,你又需要依靠自己了。如果你想深入研究Django和web API,那么你可能已經(jīng)準備好使用Django的REST框架了。它們實現(xiàn)了一整套序列化系統(tǒng),它比僅僅讓數(shù)據(jù)進行json.dump()做了更多的工作。

最后,為了完整性,我感覺我不得不提到我自己在我第一天開始就極其討厭的structlog中的解決方案:為你的類增加一個__structlog__方法,它會像__str__一樣返回一個序列化后的表示方法。請不要重復我的錯誤。標簽:software clown。

JSON已經(jīng)很流行了,然而很奇怪的是我們對于序列化的解決方案卻仍舊不夠完善。我個人想要的是能夠注冊一個中心化的序列化工具,但是卻以一個去中心化的方式來使用,這樣可以不需要對我的類(或者更糟的,第三方類)進行任何修改。

進入PEP443

Python3.4以PEP 443的形式給出了對這個問題的一個好的解決方案:functools.singledispatch(老式Python版本也可以在PyPI上找到)。

簡單說,你可以定義一個默認的函數(shù)然后根據(jù)第一個參數(shù)的類型注冊一個該函數(shù)的額外版本:

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

現(xiàn)在你也可以對datetime實例調(diào)用to_serializable()方法,singledispatch會選擇正確的函數(shù)

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

這一方法讓你能夠把你的序列化器放在任何你想放的位置:放在類里,在一個獨立的模塊里,或者放在JSON相關的代碼里。你自己選!但是你的類要保持干凈,并且你不需要巨大的繁瑣的if-elif-else分支。

更深入一點

顯然,@singledispatch的使用比JSON更加深入。一般而言,為不同類型的對象綁定不同的行為以及獨立的序列化方式是普遍適用的4。我的一些校對員提到了他們嘗試了采用字典類近似替代可調(diào)用對象以及其他一些類似的“殘暴的”做法。

換句話說,@singledispatch就是一個長久以來就存在的但是卻被你忽略的函數(shù)。

P.S. 當然,PyPI中也有一個*multiple*dispatch。

腳注

1. 然而,對于非常出名的一個:UltraJSON一點都不支持自定義對象的序列化,此外,python-rapidjson僅僅支持default()函數(shù)。

2. 利用attrs是可以很好管理的!也許你應當使用attrs!

3. 不幸的是Pyramid使用的API自從zope.component移植過來之后還沒有形成文檔。

4. 我聽說將singlepatch加進標準庫的最原始動力來自于對pprint的一個更優(yōu)雅的實現(xiàn)(雖然從來沒有實現(xiàn)過)

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

(版權歸原作者所有,侵刪)

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • API
    API
    +關注

    關注

    2

    文章

    1461

    瀏覽量

    61523
  • 函數(shù)
    +關注

    關注

    3

    文章

    4240

    瀏覽量

    61998
  • 代碼
    +關注

    關注

    30

    文章

    4674

    瀏覽量

    67804
  • python
    +關注

    關注

    53

    文章

    4753

    瀏覽量

    84106
  • JSON
    +關注

    關注

    0

    文章

    114

    瀏覽量

    6900

原文標題:更好的Python對象序列化方式

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    【《時間序列與機器學習》閱讀體驗】+ 時間序列的信息提取

    、特征的范數(shù)歸一化。每個定義和命題都給出了證明過程和示例,示例還提供了Python代碼,方便學習。 以下是特征的最小最大縮放的示例數(shù)據(jù)和代碼: 由于我的本子有Python運行環(huán)境,編輯
    發(fā)表于 08-14 18:00

    python訓練出的模型怎么調(diào)用

    使用pickle模塊 pickle 是Python內(nèi)置模塊,用于序列化和反序列化Python
    的頭像 發(fā)表于 07-11 10:15 ?945次閱讀

    鴻蒙原生應用開發(fā)-ArkTS語言基礎類庫多線程并發(fā)概述

    可以通過遞歸的方式拷貝傳輸對象,相較于其他序列化的算法,支持的對象類型更加豐富。 序列化支持的類型包括:除Symbol之外的基礎類型、Dat
    發(fā)表于 03-28 14:35

    俄勒岡州禁止數(shù)碼設備使用“序列化”技術

    該法案對諸如蘋果iPhone等數(shù)字產(chǎn)品產(chǎn)生巨大影響,意即制造商無法利用“零件序列化”技術束縛消費者選擇第三方維修服務或自主修復非原產(chǎn)部件,同時也不能以此減少設備性能或誤導使用者。
    的頭像 發(fā)表于 03-28 10:46 ?431次閱讀

    鴻蒙原生應用開發(fā)-ArkTS語言基礎類庫多線程并發(fā)概述

    可以通過遞歸的方式拷貝傳輸對象,相較于其他序列化的算法,支持的對象類型更加豐富。 序列化支持的類型包括:除Symbol之外的基礎類型、Dat
    發(fā)表于 03-22 15:40

    python輸出list的每一個元素

    使用for循環(huán)來遍歷列表,并輸出其中的每一個元素。接下來,我將詳盡、詳實、細致地介紹Python輸出列表的每一個元素的方法,希望能對你有所幫助。 首先,我們需要明確
    的頭像 發(fā)表于 11-21 16:16 ?1152次閱讀

    什么時候需要Boost序列化

    () const { return m_strName;} private :std::string m_strName;}; 然后我們想把這個類的對象保存到文件中或者通過網(wǎng)絡發(fā)出去,怎么辦呢?答案就是:把這個
    的頭像 發(fā)表于 11-10 10:14 ?349次閱讀

    protobuf的編碼和存儲方式

    中 收發(fā)兩端進行消息交互。所謂的“結構數(shù)據(jù)”是指類似于struct結構體的數(shù)據(jù),可用于表示網(wǎng)絡消息。當結構體中存在函數(shù)指針類型時,直接對其存儲或傳輸相當于是“淺拷貝”,而對其序列化后則是“深拷貝”。)
    的頭像 發(fā)表于 11-09 09:27 ?1037次閱讀
    protobuf的編碼和存儲<b class='flag-5'>方式</b>

    Python 不可變對象真的不可變嗎

    在日常的學習和工作中,經(jīng)常會遇到"不可變對象"的問題,但是隨著接觸Python這門語言的時間越來越多,遇到的坑越來越奇怪。我不禁產(chǎn)生了疑問:不可變
    的頭像 發(fā)表于 11-03 11:48 ?461次閱讀
    <b class='flag-5'>Python</b> 不可變<b class='flag-5'>對象</b>真的不可變嗎

    Python 模擬鍵盤鼠標的方式實現(xiàn)自動

    實現(xiàn)自動。 Python中模擬鍵盤和鼠標最著名的模塊是: pymouse 和 pykeyboard 。次安裝兩模塊比較麻煩,而有
    的頭像 發(fā)表于 11-02 14:48 ?1100次閱讀
    <b class='flag-5'>Python</b> 模擬鍵盤鼠標的<b class='flag-5'>方式</b>實現(xiàn)自動<b class='flag-5'>化</b>

    Pydantic:強大的數(shù)據(jù)校驗工具

    Pydantic 是使用Python類型注解進行數(shù)據(jù)驗證和管理的模塊。安裝方法非常簡單,打開終端輸入: pip install pydantic 它類似于 Django DRF 序列化
    的頭像 發(fā)表于 10-30 11:40 ?471次閱讀

    Java序列化怎么使用

    轉換方式就叫做序列化。將文件或者網(wǎng)絡傳輸中得到的 byte[] 數(shù)組轉換為 java 對象就叫做反序列化。 怎么使用 如果
    的頭像 發(fā)表于 10-10 14:19 ?356次閱讀

    Spring Boot時配置JSON序列化選項的幾種方法

    在Spring Boot Web 項目中,當使用JSON格式接收數(shù)據(jù)和返回數(shù)據(jù)的時候,Spring Boot 默認使用ObjectMapper實例來序列化響應和反序列化請求。 在本
    的頭像 發(fā)表于 10-09 10:26 ?1852次閱讀

    如何用C語言進行json的序列化和反序列化

    呢? 當前,應用最廣泛的C語言json解析庫當屬cJSON,但是,使用cJSON讀json進行序列化和反序列化,需要根據(jù)key一個一個進行處理,會導致代碼冗余,邏輯性不強,哪有沒有更好的方法呢? 思路 在Android平臺,
    的頭像 發(fā)表于 10-07 11:05 ?1255次閱讀

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

    Serde 是用于序列化和反序列化 Rust 數(shù)據(jù)結構的庫。它支持 JSON、BSON、YAML 等多種格式,并且可以自定義序列化和反
    的頭像 發(fā)表于 09-30 17:09 ?1173次閱讀