1

pickleを使用してカスタムクラスを保存しようとしています。以下のコードに非常によく似ています(ただし、クラスでいくつかのメソッドが定義されており、データにはさらにいくつかのdictなどがあります)。ただし、これを実行し、ピクルスしてからアンピクルすると、クラス内のデータがすべて失われ、新しい空白のインスタンスを作成したかのようになります。

import pickle
class MyClass:
    VERSION = 1
    some_data = {}
    more_data = set()

    def save(self,filename):
        with open(filename, 'wb') as f:
            p = pickle.Pickler(f)
            p.dump(self)

    def load(filename):
        with open(filename,'rb') as ifile:
            u = pickle.Unpickler(ifile)
            obj = u.load()
            return obj

これは漬物教室のメモと関係があるのではないかと思っていたのですが、そうあるべきではないと思います。それが機能しないとき、私は生成されたファイルを見ると、次のようになります:(明らかに読み取り可能ではありませんが、明らかにデータが含まれていません)

€c__main__
私のクラス
q

とにかく、これで誰かがここで何が起こっているのか、何を見るべきかを理解するのに十分であることを願っています。

4

1 に答える 1

8

あなたが抱えている問題は、データをインスタンス変数に入れるのではなく、可変クラス変数を使用してデータを保持していることです。

モジュールはpickle、インスタンスに直接保存されたデータのみを保存し、を介してアクセスできるクラス変数は保存しませんself。選択されていないインスタンスにデータがないことがわかった場合、それはおそらく、クラスが前回の実行からのデータを保持していないため、インスタンスがそれ以上アクセスできないことを意味します。

クラス変数をそのように使用すると、データがクラスのすべてのインスタンスで共有されるため、おそらく他の問題も発生します。この問題を説明するPythonコンソールセッションコードは次のとおりです。

>>> class Foo(object):
        class_var = []
        def __init__(self, value):
            self.class_var.append(value)

>>> f1 = Foo(1)
>>> f1.class_var
[1]
>>> f2 = Foo(2)
>>> f2.class_var
[1, 2]

それはおそらくあなたが望んでいたものではありません。しかし、それはさらに悪化します!

>>> f1.class_var
[1, 2] 

あなたが属していたと思っていたデータはf1、の作成によって変更されましたf2。実際、これf1.class_varはとまったく同じオブジェクトです(インスタンスをまったく経由せずに、直接f2.class_var経由して利用することもできます)。Foo.class_var

したがって、クラス変数を使用することは、ほぼ確実にあなたが望むものではありません。代わりに、__init__新しい値を作成してインスタンス変数として保存するクラスのメソッドを記述します。

>>> class Bar(object):
        def __init__(self, value):
            self.instance_var = [] # creates a separate list for each instance!
            self.instance_var.append(value)

>>> b1 = Bar(1)
>>> b1.instance_var
[1]
>>> b2 = Bar(2)
>>> b2.instance_var # doesn't include value from b1
[2]
>>> b1.instance_var # b1's data is unchanged
[1]

Pickleは、期待どおりにこのクラスを処理します。そのデータはすべてインスタンス内にあるため、ピックを外したときにインスタンスが空になることはありません。

于 2013-02-04T04:51:52.317 に答える