2016-07-12 4 views
0

私は別の時間に保存して再ロードしたいオブジェクトの辞書を作成しています( "json"モジュールでこれをやりたい、ピクルス ")。__dict__ Pythonでメソッド呼び出しを許可しない

私は1つのクラスを作成しました( "Ball"と呼んでください)、そのクラスの多くの異なるインスタンスが辞書に含まれています。それが見える方法は次のとおりです。

my_dict = { 
      "ball1": {"size": "big", "baseball": False, etc...}, 
      "ball2": {"size": "small", "baseball": True, etc...}, 
      etc... 
      } 

"ボール"クラスの新しいインスタンスを作成するとき、私は単にそれらを "my_dict"に追加します。

changeSize(self, size) 

問題:

私が動作するように保存能力を取得するためには

私の「ボール」のクラスは、私は特定のフィールド...すなわちの値を変更できるようにするメソッドを持っています適切に私は「ボール」クラスのそれぞれの新しいインスタンスに次の操作を実行しなければならなかったのJSONモジュールと:

を追加
newBall = Ball(name) 
my_dict[name] = newBall.__dict__ 

それを辞書に追加するとJSONはシリアライズ可能になりますが、「編集モード」に入るとメソッド(changeSize(name))を呼び出すことができなくなります辞書であり、もはや「ボール」オブジェクトではない。

私は(jsonモジュールを使用して)保存し、編集するために使用しているメソッドも使用できるようにするにはどうすればよいですか?

また、私が保存しています方法は、/ロードは次のとおりです。

out_file = open("testSave.json"), "w") 
json.dump(my_dict, out_file, indent=4) 
out_file.close() 

in_file = open("testSave.json", "r") 
my_dict = json.load(in_file) 
in_file.close() 

感謝を!

答えて

1

最終的にjsonは、任意のpythonオブジェクトのシリアル化をサポートしていません。あなたがそれをしたい場合は、pickleを見ることができます。

また、あなたがdictからの値で初期化されますあなたのBall上の代替コンストラクタを作成することができます

class Ball(object): 

    @classmethod 
    def from_json(self, dictionary): 
     b = cls() 
     b.__dict__.update(dictionary) 
     return b 

    ... 

を私はBallコンストラクタが0の引数で呼び出すことができると仮定し、これを書いています - そうでない場合、または__init__が「派手」(jsonのシリアライズ可能な属性を設定しない)を実行する場合は、コードを変更する必要があります。 __init__の引数の要件の周りの一つの方法は、インスタンスを作成するために__new__を使用して、ちょうどクラスの辞書を更新することにより、メンバーを移入することです:

class Ball(object): 
    def __init__(self, name, foo, bar): 
     self.name = name 
     self.foo = foo 
     self.bar = bar 

    def to_dict(self): 
     return self.__dict__ 

    @classmethod 
    def from_dict(cls, dictionary): 
     self = cls.__new__(cls) 
     self.__dict__.update(dictionary) 
     return self 

    def __str__(self): 
     return 'Ball(%r, %r, %r)' % (self.name, self.foo, self.bar) 


b = Ball('HockyPuck', 'flat', 'NotABall') 
d = b.to_dict() 
bb = Ball.from_dict(d) 

print(bb) 

これはpython2.xと3.xの両方で動作します

+0

'Ball'コンストラクタは最小限の名前を必要とします(しかし、プログラムではそれが起こるように促されます)。あなたが基本的に同じことをやっていたら、私はすでにそれがうまくいく「ピクルス」でやっているのですか?私はそれが安全性が低いことを知っています、そして、それが私がjsonの方法を学ぼうとしていた理由です。また、私が 'json'を続けると、なぜ'デコレータ 'を使うのかを簡単に説明できますか?私はそれらをよく理解していません。どうもありがとう! – AmericanMade

+0

@AmericanMade - あなたは 'b = cls(dictionary.get( 'name'))'やそれに類するものを実行できるかもしれません。 Re: 'pickle' - 確かにそこにセキュリティ問題があります。あなたが完全にそれを信用しないと、何かをunpickleしないでください。 '@ classmethod'に関しては、' from_json'の 'cls'がクラスのインスタンスではなく_class_であるようにしています。 – mgilson