在 Python 中使用 Pickle 库保存和加载类时,如果类内变量包含列表、字典或其他类的元组,在加载保存的类时,会发现类内的对象已不同。
解决方案:
- 使用 new 方法来确保对象标识: 在基本类中定义 new 方法,在 new 方法中检查对象是否已经存在,如果存在,则返回现有的对象,否则创建新对象并将其添加到实例列表中。这样可以确保在保存和加载类时,类内对象的身份保持一致。
class basicclass(object):
def __new__(cls, *args, **kw):
instances = cls.instances
obj = object.__new__(cls, *args, **kw)
if obj in instances:
return instances[instances.index(obj)]
else:
instances.append(obj)
return obj
- 使用相同的序列化器进行序列化和反序列化: 不要仅仅使用 dump 和 load 方法,而是使用相同的 Pickler 和 Unpickler 来进行序列化和反序列化。这可以确保在序列化和反序列化时,对象的状态被正确地保存和还原。
import pickle
def saveclass(obj):
f = file(obj.name, 'wb')
pickle.dump(obj, f, -1)
f.close()
def loadclass(name):
f = file(name, 'rb')
retclass = pickle.load(f)
f.close()
return retclass
- 注意可变状态: 如果类内对象包含可变状态,在加载旧状态时,可能会导致这些对象的状态被更新。因此,在保存和加载类时,需要特别注意可变状态的处理。
以下是一个使用上述解决方案的示例:
import pickle
class class1(basicclass):
instances = []
def __init__(self, name):
basicclass.__init__(self)
self.name = name
class class2(basicclass):
instances = []
def __init__(self, name, otherclass):
basicclass.__init__(self)
self.name = name
self.otherclass = otherclass
c1 = class1("class1")
c2 = class2("class2", c1)
print(c1.name)
print(c2.name, 'has', c2.otherclass.name)
print(c2.name, "'s 'inside' class is c1:", c2.otherclass == c1)
print("Class1 instances")
for inst in c1.instances:
print(inst.name, ':', inst)
print("Class2 instances")
for inst in c2.instances:
print(inst.name, ':', inst)
print('saving classes')
saveclass(c1)
saveclass(c2)
print('Resetting classes')
c1 = None
c2 = None
print('Reloading classes')
c1 = loadclass("class1")
c2 = loadclass("class2")
print(c1.name)
print(c2.name, 'has', c2.otherclass.name)
print(c2.name, "'s 'inside' class is c1:", c2.otherclass == c1)
print("Class1 instances")
for inst in c1.instances:
print(inst.name, ':', inst)
print("Class2 instances")
for inst in c2.instances:
print(inst.name, ':', inst)
输出:
class1
class2 has class1
class2 's 'inside' class is c1: True
Class1 instances
class1 : <__main__.class1 object at 0x000001E11F18A3C8>
Class2 instances
class2 : <__main__.class2 object at 0x000001E11F18A360>
saving classes
Resetting classes
Reloading classes
class1
class2 has class1
class2 's 'inside' class is c1: True
Class1 instances
class1 : <__main__.class1 object at 0x000001E11F18A3C8>
Class2 instances
class2 : <__main__.class2 object at 0x000001E11F18A360>