2012-05-31 60 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