假设我在文件myClass.py
中有一个简单的python类定义class Test:
A = []
我还有两个测试脚本。第一个脚本创建一个Test类型的对象,填充数组A,并将结果pickle到文件。它立即从文件中取消它,并且仍然填充了数组。 第二个脚本只是从文件中取消,并且未填充数组(即A == [])。这是为什么?
test1.py
import myClass
import pickle
x = myClass.Test()
for i in xrange(5):
x.A.append(i)
f = open('data', 'w')
pickle.dump(x,f)
f.close()
f = open('data')
y = pickle.load(f)
f.close
print y.A
和test2.py
import myClass
import pickle
f = open('data')
y = pickle.load(f)
f.close
print y.A
答案 0 :(得分:25)
这是因为您将Test.A
设置为类属性而不是实例属性。真正发生的事情是,使用test1.py,从pickle文件读回的对象与test2.py相同,但它使用最初分配给x.A
的内存中的类。
当您从文件中取消数据时,它会创建类类型的新实例,然后应用它需要的任何实例数据。但是您唯一的数据是类属性。它总是引用内存中的类,它在一个文件中修改,但不在另一个文件中修改。
比较此示例中的差异:
class Test:
A = [] # a class attribute
def __init__(self):
self.a = [] # an instance attribute
您会注意到实例属性a
将被正确地pickle和unpickled,而class属性A
将简单地引用内存中的类。
for i in xrange(5):
x.A.append(i)
x.a.append(i)
with open('data', 'w') as f:
pickle.dump(x,f)
with open('data') as f:
y = pickle.load(f)
>>> y.A
[0, 1, 2, 3, 4]
>>> y.a
[0, 1, 2, 3, 4]
>>> Test.A
[0, 1, 2, 3, 4]
>>> Test.A = [] # resetting the class attribute
>>> y.a
[0, 1, 2, 3, 4]
>>> y.A # refers to the class attribute
[]
答案 1 :(得分:2)
这是一个古老的问题,如果现在看到它,您可能想要设置班级的__getstate__
和__setstate__
,以便泡菜知道如何转储和加载定义的班级。
在此处查看examples。
如果您的类很简单(例如,只有整数和字符串作为成员以及任何方法),那么它应该可以自动选择。