引言
将对象的状态信息转换为可以存储或传输的形式的过程叫作序列化
类似地从序列化后的数据转换成相对应的对象叫作 反序列化
本文介绍 Python
将对象序列化和反序化的两个模块
- picklejson
- pickle
pickle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
# 序列化
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 |
自定义的对象也能序列化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
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
也可以把对象序列化保存到文件,然后从文件反序化回对象。
1
2
3
4
5
6
7
8
9
10
11
12
|
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()
|
从文件反序化回对象
1
2
3
4
5
6
7
8
9
10
11
12
|
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
的对象,json
和 Python
内置的数据类型对应如下:
JSON类型 | Python类型 |
---|---|
{} | dict |
[] | list |
"string" | 'str' 或 u'unicode' |
3.14 | int 或 float |
true / false | True / False |
null | None |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
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
序列化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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
模块。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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
专门写一个转换函数,再把函数传进去即可:
1
2
3
4
5
6
7
8
9
|
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
1
2
3
4
5
|
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 对象序列化内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://blog.csdn.net/qq_43629857/article/details/120542441