泡菜与自定义类

Joe*_*Joe 21 python pickle

假设我在文件myClass.py中有一个简单的python类定义

class Test:
    A = []
Run Code Online (Sandbox Code Playgroud)

我还有两个测试脚本.第一个脚本创建一个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
Run Code Online (Sandbox Code Playgroud)

和test2.py

import myClass
import pickle

f = open('data')
y = pickle.load(f)
f.close

print y.A
Run Code Online (Sandbox Code Playgroud)

jdi*_*jdi 27

这是因为您将设置Test.A为类属性而不是实例属性.真正发生的事情是,使用test1.py,从pickle文件读回的对象与test2.py相同,但它使用最初分配的内存中的类x.A.

当您从文件中取消数据时,它会创建类类型的新实例,然后应用它需要的任何实例数据.但是您唯一的数据是类属性.它总是引用内存中的类,它在一个文件中修改,但在另一个文件中没有修改.

比较此示例中的差异:

class Test:
    A = []  # a class attribute
    def __init__(self):
        self.a = []  # an instance attribute
Run Code Online (Sandbox Code Playgroud)

您会注意到实例属性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
[]
Run Code Online (Sandbox Code Playgroud)


bor*_*rgr 6

这是一个老问题,如果你现在看到它,你可能需要设置__getstate____setstate__您的类的咸菜所以会知道如何转储并加载您定义的类。

请参阅此处的示例

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