我正在尝试使用pickle来保存自定义类;与下面的代码非常相似的东西(虽然在类上定义了一些方法,还有几个dicts等数据)。但是,通常当我运行它,pickle然后unpickle时,我会丢失类中的任何数据,并且就好像我创建了一个新的空白实例。
import pickle
class MyClass:
VERSION = 1
some_data = {}
more_data = set()
def save(self,filename):
with open(filename, 'wb') as f:
p = pickle.Pickler(f)
p.dump(self)
def load(filename):
with open(filename,'rb') as ifile:
u = pickle.Unpickler(ifile)
obj = u.load()
return obj
我想知道这是否与泡菜类的备忘录有关,但我觉得不应该这样做。当它不起作用时,我会查看我生成的文件,看起来像这样:(显然不是可读的,但显然不包含数据)
€c__main__ MyClass q
无论如何,我希望这足以让某人了解这里可能会发生什么,或者看什么。
答案 0 :(得分:7)
您遇到的问题是您使用可变类变量来保存数据,而不是将数据放入实例变量中。
pickle
模块仅保存直接存储在实例上的数据,而不保存也可以通过self
访问的类变量。当您发现未修改的实例没有数据时,这可能意味着该类不保存上一次运行的数据,因此实例无法再访问它。
使用类变量可能会导致其他问题,因为数据将由类的所有实例共享!这是一个Python控制台会话代码,用于说明问题:
>>> class Foo(object):
class_var = []
def __init__(self, value):
self.class_var.append(value)
>>> f1 = Foo(1)
>>> f1.class_var
[1]
>>> f2 = Foo(2)
>>> f2.class_var
[1, 2]
这可能不是你想要的。但它变得更糟!
>>> f1.class_var
[1, 2]
您认为属于f1
的数据已因f2
的创建而发生变化。事实上,f1.class_var
与f2.class_var
是完全相同的对象(它也可以直接通过Foo.class_var
获得,而不需要经过任何实例)。
因此,使用类变量几乎肯定不是你想要的。相反,为创建新值的类编写__init__
方法并将其保存为实例变量:
>>> class Bar(object):
def __init__(self, value):
self.instance_var = [] # creates a separate list for each instance!
self.instance_var.append(value)
>>> b1 = Bar(1)
>>> b1.instance_var
[1]
>>> b2 = Bar(2)
>>> b2.instance_var # doesn't include value from b1
[2]
>>> b1.instance_var # b1's data is unchanged
[1]
Pickle将按照您的预期处理此课程。它的所有数据都在实例中,因此当你取消选择时,你永远不应该得到一个空实例。