2012-05-31 54 views
9

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

class Test: 
    A = [] 

而且我也有两个测试脚本。第一个脚本创建一个类型为Test的对象,填充数组A,并将结果粘贴到文件中。它立即从文件中取消它,并且数组仍然被填充。 第二个脚本只是从文件中取消,而数组未填充(即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 

回答

14

这是因为你设置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 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 
[] 
+0

这是否意味着,如果你有腌制类本身,'和pickle.dump(测试)',然后拆封类,你会得到正确的列表'A'早在这两种情况下? – BallpointBen

+0

@BallpointBen,不,它不会保留类的属性,因为[what-c​​an-pick-and-unpickled](https://docs.python.org/3/library/pickle.html#what-可以被腌制和不可榨取):“类被命名参考腌制,所以在不沾染环境中应用相同的限制。注意,没有任何类的代码或数据被腌制” – jdi