目录

引言

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

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

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

  • 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    

自定义的对象也能序列化

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 序列化后数据都是字节(bytes)类型

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

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

从文件反序化回对象

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

json

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

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

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
        }'
   
# 对应的反序列化
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        

看看自定义的类对象能不能 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    

报错了,说 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_dict
out[31]: {'name': 'ithui', 'sex': '男'}

in [32]: user_json = json.dumps(user_dict)

in [33]: user_json
out[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_json
out[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__ 属性照样无法正常序列化。

尾语

用 code 谱写世界,让生活更有趣。️

万水千山总是情,点赞再走行不行。️

码字不易,还望各位大侠多多支持。️

到此这篇关于python 对象序列化详细解析的文章就介绍到这了,更多相关python 对象序列化内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!