Python 對(duì)象序列化與反序列化之pickle json詳細(xì)解析
引言
將對(duì)象的狀態(tài)信息轉(zhuǎn)換為可以存儲(chǔ)或傳輸?shù)男问降倪^程叫作序列化
類似地從序列化后的數(shù)據(jù)轉(zhuǎn)換成相對(duì)應(yīng)的對(duì)象叫作 反序列化
本文介紹 Python 將對(duì)象序列化和反序化的兩個(gè)模塊
- picklejson
- pickle
pickle
# 序列化
In [19]: num = 66
In [20]: s = 'python'
In [21]: pi = 3.14
In [22]: li = [1, 2, 3]
In [27]: b_num = pickle.dumps(num)
In [28]: b_s = pickle.dumps(s)
In [29]: b_pi = pickle.dumps(pi)
In [30]: b_li = pickle.dumps(li)
In [31]: b_num
Out[31]: b'\x80\x03KB.'
In [32]: b_s
Out[32]: b'\x80\x03X\x06\x00\x00\x00pythonq\x00.'
In [33]: b_pi
Out[33]: b'\x80\x03G@\t\x1e\xb8Q\xeb\x85\x1f.'
In [34]: b_li
Out[34]: b'\x80\x03]q\x00(K\x01K\x02K\x03e.'
In [35]: type(b_li)
Out[35]: bytes
# 反序列化
In [47]: pickle.loads(b_num)
Out[47]: 66
In [48]: pickle.loads(b_s)
Out[48]: 'python'
In [49]: pickle.loads(b_pi)
Out[49]: 3.14
In [50]: li = pickle.loads(b_li)
In [51]: li
Out[51]: [1, 2, 3]
In [52]: type(li)
Out[52]: list
自定義的對(duì)象也能序列化
class User:
def __init__(self, name, sex):
self.name = name
self.sex = sex
In [38]: user = User('hui', '男')
In [39]: b_user = pickle.dumps(user)
In [40]: b_user
Out[40]: b'\x80\x03c__main__\nUser\nq\x00)\x81q\x01}q\x02(X\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00huiq\x04X\x03\x00\x00\x00sexq\x05X\x03\x00\x00\x00\xe7\x94\xb7q\x06ub.'
In [41]: type(b_user)
Out[41]: bytes
In [42]: user = pickle.loads(b_user)
In [43]: type(user)
Out[43]: __main__.User
In [44]: user.name
Out[44]: 'hui'
In [45]: user.sex
Out[45]: '男'
注意:pickle 序列化后數(shù)據(jù)都是字節(jié)(bytes)類型
pickle 也可以把對(duì)象序列化保存到文件,然后從文件反序化回對(duì)象。
import pickle
class User:
def __init__(self, name, sex):
self.name = name
self.sex = sex
user = User('ithui', '男')
f = open('user.txt', mode='wb')
pickle.dump(user, f)
f.close()
從文件反序化回對(duì)象
In [3]: f = open('user.txt', 'rb')
...: user = pickle.load(f)
...: f.close()
...:
In [4]: user
Out[4]: <__main__.User at 0x16c58ebef08>
In [5]: user.name
Out[5]: 'ithui'
In [6]: user.sex
Out[6]: '男'
pickle 模塊雖然可以將對(duì)象序列化,但它只適用于 Python 語言,所以不方便數(shù)據(jù)交換。例如你將數(shù)據(jù)發(fā)給前端,js 則無法將數(shù)據(jù)轉(zhuǎn)成自己想要的。
json
如果我們要在不同的編程語言之間傳遞對(duì)象,就必須把對(duì)象序列化為標(biāo)準(zhǔn)格式,比如 json,因?yàn)?json 表示出來就是一個(gè)字符串,可以被所有語言讀取,也可以方便地存儲(chǔ)到磁盤或者通過網(wǎng)絡(luò)傳輸進(jìn)行數(shù)據(jù)交換。
json 字符串表示的對(duì)象就是 js 的對(duì)象,json 和 Python 內(nèi)置的數(shù)據(jù)類型對(duì)應(yīng)如下:
| JSON類型 | Python類型 |
|---|---|
| {} | dict |
| [] | list |
| "string" | 'str' 或 u'unicode' |
| 3.14 | int 或 float |
| true / false | True / False |
| null | None |
In [7]: import json
In [8]: info_dict = {
...: 'name': 'hui',
...: 'age': 22,
...: 'is_admin': True,
...: 'hobbies': ['下象棋', '寫代碼'],
...: 'other': None
...: }
In [9]: info_json = json.dumps(info_dict)
In [10]: info_json
Out[10]: '{
"name": "hui",
"age": 22,
"is_admin": true,
"hobbies": ["\\u4e0b\\u8c61\\u68cb", "\\u5199\\u4ee3\\u7801"],
"other": null
}'
# 對(duì)應(yīng)的反序列化
In [16]: info_d = json.loads(info_json)
In [17]: info_d
Out[17]:
{'name': 'hui',
'age': 22,
'is_admin': True,
'hobbies': ['下象棋', '寫代碼'],
'other': None}
In [18]: type(info_d)
Out[18]: dict
看看自定義的類對(duì)象能不能 json 序列化
In [21]: import json
In [22]: class User:
...:
...: def __init__(self, name, sex):
...: self.name = name
...: self.sex = sex
...:
In [23]: user = User('ithui', '男')
In [24]: json.dumps(user)
TypeError: Object of type User is not JSON serializable
報(bào)錯(cuò)了,說 User 對(duì)象不能 json 序列化。有沒有方法可以讓自定義的對(duì)象可以轉(zhuǎn)成 json,肯定是有的。
大致思路就是先把User對(duì)象轉(zhuǎn)成可以被 json 序列化的對(duì)象,例如 dict 等,然后再把可序列化的對(duì)象給 json 模塊。
In [28]: def user2dict(obj):
...: return {'name': obj.name, 'sex': obj.sex}
...:
...:
In [29]: user = User('ithui', '男')
In [30]: user_dict = user2dict(user)
In [31]: user_dict
Out[31]: {'name': 'ithui', 'sex': '男'}
In [32]: user_json = json.dumps(user_dict)
In [33]: user_json
Out[33]: '{"name": "ithui", "sex": "\\u7537"}'
也可以在序列化的時(shí)候指定一個(gè)轉(zhuǎn)換器,可選參數(shù) default 就是把任意一個(gè)對(duì)象變成一個(gè)可序列為JSON的對(duì)象,我們只需要為 User 專門寫一個(gè)轉(zhuǎn)換函數(shù),再把函數(shù)傳進(jìn)去即可:
In [28]: def user2dict(obj):
...: return {'name': obj.name, 'sex': obj.sex}
...:
...:
In [34]: user_json = json.dumps(user, default=user2dict)
In [35]: user_json
Out[35]: '{"name": "ithui", "sex": "\\u7537"}'
這樣雖然可以把自定義的類對(duì)象轉(zhuǎn)換成 json 但是要為不同的類專門定制不同的轉(zhuǎn)換器,重復(fù)又麻煩,因此想到利用的每個(gè)類的 __dict__ 屬性來序列化,它是一個(gè) dict 對(duì)象,用來存儲(chǔ)實(shí)例變量。也有少數(shù)例外,比如定義了 __slots__ 的 class
In [36]: user.__dict__
Out[36]: {'name': 'ithui', 'sex': '男'}
In [41]: json.dumps(user.__dict__)
Out[41]: '{"name": "ithui", "sex": "\\u7537"}'
注意:如果是對(duì)象中的屬性又嵌套另一個(gè)不能直接 json 序列化的對(duì)象,使用 __dict__ 屬性照樣無法正常序列化。
尾語
✍ 用 Code 譜寫世界,讓生活更有趣。❤️
✍ 萬水千山總是情,點(diǎn)贊再走行不行。❤️
✍ 碼字不易,還望各位大俠多多支持。❤️
到此這篇關(guān)于Python 對(duì)象序列化詳細(xì)解析的文章就介紹到這了,更多相關(guān)Python 對(duì)象序列化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python序列化模塊之pickle與json詳解
- Python常用標(biāo)準(zhǔn)庫詳解(pickle序列化和JSON序列化)
- Python 解析庫json及jsonpath pickle的實(shí)現(xiàn)
- Python標(biāo)準(zhǔn)庫json模塊和pickle模塊使用詳解
- Python之?dāng)?shù)據(jù)序列化(json、pickle、shelve)詳解
- Python3.5 Json與pickle實(shí)現(xiàn)數(shù)據(jù)序列化與反序列化操作示例
- Python序列化基礎(chǔ)知識(shí)(json/pickle)
- 簡單談?wù)凱ython中的json與pickle
- 詳解Python之?dāng)?shù)據(jù)序列化(json、pickle、shelve)
- Python序列化模塊JSON與Pickle
相關(guān)文章
Pycharm使用之設(shè)置代碼字體大小和顏色主題的教程
今天小編就為大家分享一篇Pycharm使用之設(shè)置代碼字體大小和顏色主題的教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-07-07
Python實(shí)現(xiàn)正弦信號(hào)的時(shí)域波形和頻譜圖示例【基于matplotlib】
這篇文章主要介紹了Python實(shí)現(xiàn)正弦信號(hào)的時(shí)域波形和頻譜圖,涉及Python數(shù)學(xué)運(yùn)算與圖形繪制相關(guān)操作技巧,需要的朋友可以參考下2018-05-05
Windows下python3安裝tkinter的問題及解決方法
這篇文章主要介紹了Windows下python3安裝tkinter問題及解決方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-01-01
Python解方程組 scipy.optimize.fsolve()函數(shù)如何求解帶有循環(huán)求和的方程式
這篇文章主要介紹了Python解方程組 scipy.optimize.fsolve()函數(shù)如何求解帶有循環(huán)求和的方程式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06
pandas 數(shù)據(jù)結(jié)構(gòu)之Series的使用方法
這篇文章主要介紹了pandas 數(shù)據(jù)結(jié)構(gòu)之Series的使用方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06

