2012-05-31 5 views
9

私は、ファイルmyClass.pyにピクルス

class Test: 
    A = [] 

を簡単なPythonのクラス定義を持っていると私は、2つのテストスクリプトがあるとします。最初のスクリプトは、タイプTestのオブジェクトを作成し、配列Aに値を設定し、結果をファイルにpickleします。それはすぐにファイルからそれをunpickleし、配列はまだ入力されます。 2番目のスクリプトは、ファイルから少しだけ離れていて、は配列に入力されていません(つまり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に割り当てられていたメモリ内のクラスを使用しています。

データがファイルからアンピクルされている場合、クラスタイプの新しいインスタンスが作成され、必要なインスタンスデータが適用されます。しかし、あなたの唯一のデータはクラス属性でした。そのクラスは常にメモリ内のクラスを参照していますが、これは1つで修正されていますが、別のファイルでは修正されていません。

は、この例の違いを比較:

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

あなたは、インスタンスがクラス属性Aは、単にメモリ内のクラスを参照する一方aは、適切に漬けと逆pickle化される属性のことがわかります。

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-be-pickled-and-unpickled](https://docs.python.org/3/library/pickle.html#what- "pickle-un-pickle-unpickled"): "名前付き参照によってクラスが節約されるので、unpickle環境の同じ制限が適用されます。クラスのコードまたはデータは、 – jdi

関連する問題