python中如果我改了自己之前的类代码,那以前的序列化对象还能反序列化回来吗?
着急的可以跳过代码,直接看底下的结论.
class DemoClass:
#初始版本
def __init__(self,v1,v2,v3):
self.v1=v1
self.v2=v2
self.v3=v3
#初始版本
def f1(self,vf11,vf12):
print("我是即将要修改的部分")
return vf11+vf12
#初始版本,作为被删除的那个函数
# def f2(self,vf21,vf22):
# return vf21-vf22
#这个函数不能变,用来测试反序列化得到的对象能否正常使用
def test1(self,testVarieble):
print("受到的参数是,能看到这一行字说明测试函数一可以使用",testVarieble)
'''1.1.增加新的方法,没有使用到成员变量
def newf(self):
print('我是一个新的方法')'''
"""增加的新方法,要用到成员变量了
def getv1(self):
return v1"""
'''def bbbb(self):
print("稀奇古怪")'''
'''这里看对原来的对象展示一下换名字的变量'''
# def showv4(self):
# print(self.v4)
底下的是测试文件:
import pickle
'''
下面说一下我最关心的问题,自定义对象的序列化和反序列化:
1.如果原来的类定义文件发生了改变,还能不能反序列化,如果不能,怎样才能?
1.成员方法层面:
1.增加新的方法,
2.删除原来的方法,
3.对原来的方法体做出修改
4.对原来的方法的参数列表做出修改
2.成员变量层面(其实这也算是对成员方法的修改):
1.增加成员变量
2.删除现有的成员变量
2.和import语句有没有关系?是不是只要导入正确的类就行?
'''
import 储存问题.序列化与反序列化.DemoClass as dm
demo=dm.DemoClass("第一个成员变量v1","第一个成员变量v2","第一个成员变量v3")
result=pickle.dumps(demo)
print(result)
#原始序列化结果(什么改动都没有): b'\x80\x04\x95\xa6\x00\x00\x00\x00\x00\x00\x00\x8c/\xe5\x82\xa8\xe5\xad\x98\xe9\x97\xae\xe9\xa2\x98.\xe5\xba\x8f\xe5\x88\x97\xe5\x8c\x96\xe4\xb8\x8e\xe5\x8f\x8d\xe5\xba\x8f\xe5\x88\x97\xe5\x8c\x96.DemoClass\x94\x8c\tDemoClass\x94\x93\x94)\x81\x94}\x94(\x8c\x02v1\x94\x8c\x17\xe7\xac\xac\xe4\xb8\x80\xe4\xb8\xaa\xe6\x88\x90\xe5\x91\x98\xe5\x8f\x98\xe9\x87\x8fv1\x94\x8c\x02v2\x94\x8c\x17\xe7\xac\xac\xe4\xb8\x80\xe4\xb8\xaa\xe6\x88\x90\xe5\x91\x98\xe5\x8f\x98\xe9\x87\x8fv2\x94\x8c\x02v3\x94\x8c\x17\xe7\xac\xac\xe4\xb8\x80\xe4\xb8\xaa\xe6\x88\x90\xe5\x91\x98\xe5\x8f\x98\xe9\x87\x8fv3\x94ub.'
'''
成员方法:
增加一个成员方法后(该方法未使用成员变量):b'\x80\x04\x95\xa6\x00\x00\x00\x00\x00\x00\x00\x8c/\xe5\x82\xa8\xe5\xad\x98\xe9\x97\xae\xe9\xa2\x98.\xe5\xba\x8f\xe5\x88\x97\xe5\x8c\x96\xe4\xb8\x8e\xe5\x8f\x8d\xe5\xba\x8f\xe5\x88\x97\xe5\x8c\x96.DemoClass\x94\x8c\tDemoClass\x94\x93\x94)\x81\x94}\x94(\x8c\x02v1\x94\x8c\x17\xe7\xac\xac\xe4\xb8\x80\xe4\xb8\xaa\xe6\x88\x90\xe5\x91\x98\xe5\x8f\x98\xe9\x87\x8fv1\x94\x8c\x02v2\x94\x8c\x17\xe7\xac\xac\xe4\xb8\x80\xe4\xb8\xaa\xe6\x88\x90\xe5\x91\x98\xe5\x8f\x98\xe9\x87\x8fv2\x94\x8c\x02v3\x94\x8c\x17\xe7\xac\xac\xe4\xb8\x80\xe4\xb8\xaa\xe6\x88\x90\xe5\x91\x98\xe5\x8f\x98\xe9\x87\x8fv3\x94ub.'
结果:与原始对象序列化的结果相同,可以使用各项功能,包括新增的函数
结论:没有影响
删除一个成员方法(该方法未使用成员变量),向一个函数中多加一句话,以及对使用到成员变量的成员变量进行以上操作
结果:与上面那个相同
结论:任意修改一个没有使用成员变量的成员方法无影响
导包:
把as后面那个dm改成dm1,没有影响
把文件"序列化与反序列化"改为"序列化与反序列化1",反序列化不行了,找不到模块了,再改回 原来的包名,就有可以了
构造函数:
给原来的所有v3换成v4,理论上没有真正的改变类,这时:
1.可以反序列化,但是构造时相同的参数列表,序列化得到的结果却不同
2.当对原始数据调用使用v4的函数时会报错,'DemoClass' object has no attribute 'v4'
3.如果我把使用v4的函数注释掉,当还是反序列并且得到化上一步的有该方法的对象,然后调用使用v4的方法,结果无疑报错
'''
原始数据结果=b'\x80\x04\x95\xa6\x00\x00\x00\x00\x00\x00\x00\x8c/\xe5\x82\xa8\xe5\xad\x98\xe9\x97\xae\xe9\xa2\x98.\xe5\xba\x8f\xe5\x88\x97\xe5\x8c\x96\xe4\xb8\x8e\xe5\x8f\x8d\xe5\xba\x8f\xe5\x88\x97\xe5\x8c\x96.DemoClass\x94\x8c\tDemoClass\x94\x93\x94)\x81\x94}\x94(\x8c\x02v1\x94\x8c\x17\xe7\xac\xac\xe4\xb8\x80\xe4\xb8\xaa\xe6\x88\x90\xe5\x91\x98\xe5\x8f\x98\xe9\x87\x8fv1\x94\x8c\x02v2\x94\x8c\x17\xe7\xac\xac\xe4\xb8\x80\xe4\xb8\xaa\xe6\x88\x90\xe5\x91\x98\xe5\x8f\x98\xe9\x87\x8fv2\x94\x8c\x02v3\x94\x8c\x17\xe7\xac\xac\xe4\xb8\x80\xe4\xb8\xaa\xe6\x88\x90\xe5\x91\x98\xe5\x8f\x98\xe9\x87\x8fv3\x94ub.'
#原始数据结果=b'\x80\x04\x95\xa6\x00\x00\x00\x00\x00\x00\x00\x8c/\xe5\x82\xa8\xe5\xad\x98\xe9\x97\xae\xe9\xa2\x98.\xe5\xba\x8f\xe5\x88\x97\xe5\x8c\x96\xe4\xb8\x8e\xe5\x8f\x8d\xe5\xba\x8f\xe5\x88\x97\xe5\x8c\x96.DemoClass\x94\x8c\tDemoClass\x94\x93\x94)\x81\x94}\x94(\x8c\x02v1\x94\x8c\x17\xe7\xac\xac\xe4\xb8\x80\xe4\xb8\xaa\xe6\x88\x90\xe5\x91\x98\xe5\x8f\x98\xe9\x87\x8fv1\x94\x8c\x02v2\x94\x8c\x17\xe7\xac\xac\xe4\xb8\x80\xe4\xb8\xaa\xe6\x88\x90\xe5\x91\x98\xe5\x8f\x98\xe9\x87\x8fv2\x94\x8c\x02v4\x94\x8c\x17\xe7\xac\xac\xe4\xb8\x80\xe4\xb8\xaa\xe6\x88\x90\xe5\x91\x98\xe5\x8f\x98\xe9\x87\x8fv3\x94ub.'
#判断改变前后的同一对象序列化后的结果是否相同
print(result==原始数据结果)
#看最开始序列化后得到的结果用现在的类文件还能不能反序列化
原始对象=pickle.loads(原始数据结果)
#测试此对象是否能使用
原始对象.test1("ss")
#原始对象.showv4()
transient
我猜想序列化只要记录这么几个信息:
1.类的路径(带包名)
2.成员变量(变量名称和变量的值)
并且反序列化的步骤如下:
1.按照储存的类路径找到这个对象的类
2.按照储存的变量名称和变量的值走构造方法创建一个该类的实例.