Python类方法中self赋值pickle.loads未成功生效问题解决
问题根因
这个问题和pickle.dumps/pickle.loads的序列化反序列化逻辑无关,是Python变量赋值的基础机制导致的:
- 类实例方法里的
self本质是一个局部变量,调用方法时它初始指向传入的实例对象 - 你在方法内写
self = pickle.loads(pickle_data),只是修改了这个局部变量的指向,让它指向反序列化生成的新对象,完全没有改动外部提前创建的b实例的任何属性 - 你在方法内打印的正确
_data_dict值,实际是那个临时生成的反序列化对象的属性,和外部的b实例没有任何关系。方法执行结束后这个局部变量就被回收,外部的b还是一开始执行A(2)创建的实例,它的_data_dict从初始化开始就是空字典,自然打印结果不符合预期。
解决方案
提供两种可直接运行的正确实现方式:
方案1:直接接收反序列化返回的实例(推荐)
pickle.loads本身就会返回完整的反序列化对象,不需要提前创建空实例再在方法内赋值,直接接收返回值即可:
import pickle class A(): def __init__(self, nid): self.nid = nid self._data_dict = {} def initData(self, nid, pickle_data=None): if nid == 2: print("use pickle") return pickle.loads(pickle_data) else: print("normal") self._data_dict['key'] = 1 return self if __name__ == '__main__': a = A(1) a.initData(1) print(f"a _data_dict::{a._data_dict}") pickle_data = pickle.dumps(a, 0) print('-'*100) b = A(2).initData(2, pickle_data) print(f"b _data_dict::{b._data_dict}")
方案2:必须保留提前创建实例逻辑时,拷贝属性到当前实例
如果业务要求必须先创建b实例再调用初始化方法,不要直接替换self,而是把反序列化对象的所有属性更新到当前实例上:
import pickle class A(): def __init__(self, nid): self.nid = nid self._data_dict = {} def initData(self, nid, pickle_data=None): if nid == 2: print("use pickle") load_obj = pickle.loads(pickle_data) # 将反序列化对象的属性同步到当前实例 self.__dict__.update(load_obj.__dict__) print(f"pickle loads _data_dict:{self._data_dict}") else: print("normal") self._data_dict['key'] = 1 if __name__ == '__main__': a = A(1) a.initData(1) print(f"a _data_dict::{a._data_dict}") pickle_data = pickle.dumps(a, 0) print('-'*100) b = A(2) b.initData(2, pickle_data) print(f"b _data_dict::{b._data_dict}")
运行结果
两种方案修改后输出均符合预期:
normal a _data_dict::{'key': 1} ---------------------------------------------------------------------------------------------------- use pickle pickle loads _data_dict:{'key': 1} b _data_dict::{'key': 1}
内容的提问来源于stack exchange,提问作者xin.chen
相关产品推荐
相关产品推荐

