当前位置:科技动态 > (python)序列化自定义对象总结--改了类文件的代码之前的序列化自定义对象怎么办?

(python)序列化自定义对象总结--改了类文件的代码之前的序列化自定义对象怎么办?

  • 发布:2023-09-09 17:38

python中如果我改了自己之前的类代码,那以前的序列化对象还能反序列化回来吗?

着急的可以跳过代码,直接看底下的结论.

class DemoClass:#初始版本def __init__(self,v1,v2,v3):self.v1=v1self.v2=v2self.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.按照储存的变量名称和变量的值走构造方法创建一个该类的实例.

 

结论是:

只要 1.类路径的写法不变,2.构造方法不变(形参可以变,但是成员变量的名称不能变)

反序列化就一般没有问题.

如果条件限制得更严格一点,

即如果只改变了成员方法,构造时给的参数一样,那么甚至序列化的结果就是一摸一样的.

 

 

 

相关文章