忘记从谁的主页记的笔记了,Sorry
一、pickle Module
通过将对象序列化可以将其以字节(byte)的形式存储在变量或文件中,可以保存当时对象的状态,实现其生命周期的延长,并且需要时可以再次将这个对象读取出来。
1、将对象存在变量中,返回存入的字节(pickle.dumps(obj) , pickle.loads(byte_obj))
<prickling>
>>>import pickle
>>>d={'name':'Bob','age':6}
>>>byte_d= pickle.dumps(dic) # now pickling,此时,数据以字节的形式保存在byte_d变量中,需要使用的时候用loads函数unpickling还原出来
>>>print(byte_d)
b'\............\x00\x80\.................' #打印出来,可见是字节的形式
<unprickling>
>>>import pickle
>>>obj=pickle.loads(byte_b)
>>>print(obj)
{'name':'Bob','age':6}
2、将对象存在文件中,返回存入的字节(pickle.dump(obj,f) , pickle.load(f))
也可以将对象存入file-like object中,使得对象持久化,使用的是dump和load函数(没有s);由于pickle写入的是二进制数据,所以打开方式要以wb和rb的模式
<pickling>
>>>import pickle
>>>with open('am.txt','wb') as f: #在当前工作目录notepad下新建了一个可写入文件am.txt
d={'name':'Bob','age':6}
pickle.dump(d,f)
#或者也可以这样:
>>>d={'name':'Bob','age':6}
>>>f=open('am.txt','wb')
>>>pickle.dump(d,f)
>>>f.close() #别忘了
>>>print(f)
<_io.BufferedReader name='mm.txt'>
<unpickling>
>>>with open('am.txt','rb') as f:
ff=pickle.load(f) #byte to dict
print(ff)
...
{'name':'Bob','age':6}
3、序列化用户自定义对象: pickle当然也能写入,不仅可以写入类本身,也可以写入它的实例
>>>class Student():
def __init__(self,name,age,behave):
self.name=name
self.age=age
self.behave=behave
def behavior(self):
print('%s behaves %s', % (self.name, self.behave))
#将实例存储在变量中,当然也能存在file-like Object中
>>>bob = Student('Bobby',7,'Good')
>>>import pickle
>>>byte_bob = pickle.dumps(bob) #将转化为字节后的实例bob存在变量byte_bob中
>>>byte_bob
b'\x80\x03c__main__\....................\'
#unpickling还原
>>>bob=pickle.loads(byte_bob)
>>>bob.name
'Bobby'
>>>bob.behavior()
Bobby behaves Good
二、 json Module
pickle可以很方便的序列化所有对象,不过json作为更为标准的格式,具有更好的可读性(pickle是二进制数据)和跨平台性,json使用的四个函数名和pickle一致
(一)序列化为字符串
>>>import json
#序列化,dict to str
>>>d={'name':'Bob','age':6}
>>>d_str = json.dumps(d)
<class 'str'>{"name":"Bob","age":6}
#反序列化,还原,str to dict
>>>d_obj=json.loads(d_str)
<class 'dict'>{'name':'Bob','age':6}
#可见,dumps函数将对象转换成字符串,loads函数又将其恢复为字典
(二)也可以存在file-like Object中
>>>d={'name':'Bob','age':6}
>>>import json
>>>with open('mm.txt','w') as f: #由于是变成str,所以为w模式
json.dump(d,f)
#反序列化还原
>>>with open('mm.txt','r') as f:
print(json.load(f))
(三)存储自定义对象——json中,对于用户自定义的类和类实例,如果直接序列化会报错
>>>class Student():
def __init__(self,name,age,behave):
self.name=name
self.age=age
self.behave=behave
def behavior(self):
print('%s hehaves %s' % (self.name,self.behave))
>>>bob=Student('Bobby',6,'Good')
>>>import json
>>>with open('am.txt','w') as f:
json.dump(bob,f)
TypeError:object of type 'Student' is not Json Serializable
错误的原因是Student
对象不是一个可序列化为JSON的对象。
dumps()
方法的参数除了第一个必须的obj
参数外,还提供了很多可选参数,这些可选参数就是让我们来定制JSON序列化。前面的代码之所以无法把Student
类实例序列化为JSON,是因为默认情况下,dumps()
方法不知道如何将Student
实例变为一个JSON的dict对象。
可选参数default
就是把任意一个对象变成一个可序列为JSON的对象,我们只需要为Student
专门写一个转换函数,将类实例转换为dict,再把函数作为参数传进去即可:
def stu2Dict(stu):
return {'name': stu.name, 'age':stu.age, 'behave':stu.behave} # 这样就返回一个字典了
>>>print(json.dumps(bob, default=stu2Dict))
{'name':'Bobby','age':6,'behave':'Good'} # 实例bob变成了一个字典
同常class实例有一个__dict__属性,它就是一个dict,用来存储实例变量,可以偷个懒,把任意class的实例变为dict:
>>>print(json.dumps(bob,default=lambda obj: obj.__dict__))
同时,在读取的时候load出来的是一个字典,需要再转化为类实例,同样需要一个object_hook参数,该参数接受一个函数,该函数用于将字典转化为对象:
>>>def dict2Stu(d):
return Student(d['name'],d['age'],d['behave']) #由字典变为了实例对象
完整程序如下:
>>>import json
>>>with open('am.txt','w') as f:
json.dump(bob,f,default=lamba obj: obj.__dict__)
>>>def dict2Stu(d):
return Student(d['name'],d['age'],d['behave'])
>>>with open('am.txt','r') as f:
bob = json.load(f,object_hook(dict2Stu))
print(bob.name,bob.age.bob.behave)
bob.behavior()