千家信息网

如何理解Python对象序列化与反序列化

发表于:2024-09-22 作者:千家信息网编辑
千家信息网最后更新 2024年09月22日,这篇文章主要讲解了"如何理解Python对象序列化与反序列化",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何理解Python对象序列化与反序列化"吧
千家信息网最后更新 2024年09月22日如何理解Python对象序列化与反序列化

这篇文章主要讲解了"如何理解Python对象序列化与反序列化",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何理解Python对象序列化与反序列化"吧!

目录
  • 引言

  • pickle

  • json

  • 尾语

引言

将对象的状态信息转换为可以存储或传输的形式的过程叫作序列化

类似地从序列化后的数据转换成相对应的对象叫作 反序列化

本文介绍 Python 将对象序列化和反序化的两个模块

  • picklejson

  • pickle

pickle

# 序列化In [19]: num = 66In [20]: s = 'python'In [21]: pi = 3.14In [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_numOut[31]: b'\x80\x03KB.'In [32]: b_sOut[32]: b'\x80\x03X\x06\x00\x00\x00pythonq\x00.'In [33]: b_piOut[33]: b'\x80\x03G@\t\x1e\xb8Q\xeb\x85\x1f.'In [34]: b_liOut[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]: 66In [48]: pickle.loads(b_s)Out[48]: 'python'In [49]: pickle.loads(b_pi)Out[49]: 3.14In [50]: li = pickle.loads(b_li)In [51]: liOut[51]: [1, 2, 3]In [52]: type(li)Out[52]: list

自定义的对象也能序列化

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_userOut[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]: bytesIn [42]: user = pickle.loads(b_user)In [43]: type(user)Out[43]: __main__.UserIn [44]: user.nameOut[44]: 'hui'In [45]: user.sexOut[45]: '男'

注意:pickle 序列化后数据都是字节(bytes)类型

pickle 也可以把对象序列化保存到文件,然后从文件反序化回对象。

import pickleclass 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()

从文件反序化回对象

In [3]: f = open('user.txt', 'rb')   ...: user = pickle.load(f)   ...: f.close()   ...: In [4]: userOut[4]: <__main__.User at 0x16c58ebef08>In [5]: user.nameOut[5]: 'ithui'In [6]: user.sexOut[6]: '男'

pickle 模块虽然可以将对象序列化,但它只适用于 Python 语言,所以不方便数据交换。例如你将数据发给前端,js 则无法将数据转成自己想要的。

json

如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如 json,因为 json 表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输进行数据交换。

json 字符串表示的对象就是 js 的对象,jsonPython 内置的数据类型对应如下:

JSON类型Python类型
{}dict
[]list
"string"'str' 或 u'unicode'
3.14int 或 float
true / falseTrue / False
nullNone
In [7]: import jsonIn [8]: info_dict = {   ...:     'name': 'hui',   ...:     'age': 22,   ...:     'is_admin': True,   ...:     'hobbies': ['下象棋', '写代码'],   ...:     'other': None   ...: }In [9]: info_json = json.dumps(info_dict)In [10]: info_jsonOut[10]: '{                    "name": "hui",                     "age": 22,              "is_admin": true,              "hobbies": ["\\u4e0b\\u8c61\\u68cb", "\\u5199\\u4ee3\\u7801"],              "other": null        }'   # 对应的反序列化In [16]: info_d = json.loads(info_json)In [17]: info_dOut[17]:{'name': 'hui', 'age': 22, 'is_admin': True, 'hobbies': ['下象棋', '写代码'], 'other': None}In [18]: type(info_d)Out[18]: dict

看看自定义的类对象能不能 json 序列化

In [21]: import jsonIn [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

报错了,说 User 对象不能 json 序列化。有没有方法可以让自定义的对象可以转成 json,肯定是有的。

大致思路就是先把User对象转成可以被 json 序列化的对象,例如 dict 等,然后再把可序列化的对象给 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_dictOut[31]: {'name': 'ithui', 'sex': '男'}In [32]: user_json = json.dumps(user_dict)In [33]: user_jsonOut[33]: '{"name": "ithui", "sex": "\\u7537"}'

也可以在序列化的时候指定一个转换器,可选参数 default 就是把任意一个对象变成一个可序列为JSON的对象,我们只需要为 User 专门写一个转换函数,再把函数传进去即可:

In [28]: def user2dict(obj):    ...:     return {'name': obj.name, 'sex': obj.sex}    ...:    ...:        In [34]: user_json = json.dumps(user, default=user2dict)In [35]: user_jsonOut[35]: '{"name": "ithui", "sex": "\\u7537"}'

这样虽然可以把自定义的类对象转换成 json 但是要为不同的类专门定制不同的转换器,重复又麻烦,因此想到利用的每个类的 __dict__ 属性来序列化,它是一个 dict 对象,用来存储实例变量。也有少数例外,比如定义了 __slots__class

In [36]: user.__dict__Out[36]: {'name': 'ithui', 'sex': '男'}    In [41]: json.dumps(user.__dict__)Out[41]: '{"name": "ithui", "sex": "\\u7537"}'

注意:如果是对象中的属性又嵌套另一个不能直接 json 序列化的对象,使用 __dict__ 属性照样无法正常序列化。

感谢各位的阅读,以上就是"如何理解Python对象序列化与反序列化"的内容了,经过本文的学习后,相信大家对如何理解Python对象序列化与反序列化这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0