泡菜与自定义类

时间:2012-05-31 23:21:09

标签: python pickle

假设我在文件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

2 个答案:

答案 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

如果您的类很简单(例如,只有整数和字符串作为成员以及任何方法),那么它应该可以自动选择。