36

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

class Test:
    A = []

而且我还有两个测试脚本。第一个脚本创建一个 Test 类型的对象,填充数组 A,并将结果腌制到一个文件中。它立即将其从文件中解开,并且仍然填充数组。第二个脚本只是从文件中提取出来,并且没有填充数组(即 A == [])。为什么是这样?

测试1.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
4

2 回答 2

41

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

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

比较此示例中的差异:

class Test:
    A = []  # a class attribute
    def __init__(self):
        self.a = []  # an instance attribute

您会注意到实例属性a将被正确地腌制和取消腌制,而类属性A将简单地引用内存中的类。

for i in range(5):
    x.A.append(i)
    x.a.append(i)  

with open('data', 'wb') as f:
    pickle.dump(x,f)

with open('data', 'rb') 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
[]
于 2012-05-31T23:29:10.830 回答
8

__getstate__这是一个老问题,如果你现在看到它,你可能想要设置__setstate__你的类,这样泡菜就会知道如何转储和加载你定义的类。

请参阅此处的示例

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

于 2020-03-12T16:34:47.247 回答