ファイルmyClass.pyに単純なpythonクラス定義があるとします。
class Test:
A = []
また、2つのテストスクリプトもあります。最初のスクリプトは、タイプTestのオブジェクトを作成し、配列Aにデータを入力して、結果をファイルにピクルします。それはすぐにファイルからそれを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
これは、インスタンス属性ではなくクラス属性としてTest.A
を設定しているためです。実際に起こっていることは、test1.pyでは、pickleファイルから読み戻されるオブジェクトはtest2.pyと同じですが、最初にx.A
を割り当てたメモリ内のクラスを使用することです。
データがファイルからアンピックルされると、クラス型の新しいインスタンスが作成され、必要なインスタンスデータがすべて適用されます。しかし、あなたの唯一のデータはクラス属性でした。それは常に、メモリ内のクラスthatsを参照します。これは、1つのファイルでは変更されましたが、別のファイルでは変更されていません。
この例の違いを比較します。
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
[]
これは古い質問です。もし今それを見たなら、おそらく__getstate__
および__setstate__
をクラスに追加すると、定義したクラスをダンプしてロードする方法がpickleにわかります。
examples を参照してください。
クラスが単純な場合(たとえば、メンバーとメソッドとしてintとstringのみを使用する場合)、自動的に選択可能になるはずです。