2016-07-12 3 views
0

Ich erstelle ein Wörterbuch von Objekten, die ich zu einem anderen Zeitpunkt speichern und erneut laden möchte (ich möchte dies mit dem "json" -Modul tun, nicht " Essiggurke").__dict__ Erlaube Call to Method in Python nicht

Ich habe eine Klasse erstellt (nennen wir es "Ball"), und das Wörterbuch enthält nur viele verschiedene Instanzen dieser Klasse. So wie es aussieht, ist:

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

Wie ich neue Instanzen der „Ball“ Klasse erstellen, ich APPEND sie nur auf „my_dict“.

Mein „Ball“ Klasse hat Methoden, die mir erlauben, den Wert bestimmter Felder zu ändern ... das heißt:

changeSize(self, size) 

PROBLEM:

Um für mich, die sparen Fähigkeit, an die Arbeit

newBall = Ball(name) 
my_dict[name] = newBall.__dict__ 

Hinzufügen des

: richtig mit dem json-Modul ich habe folgendes auf jede neue Instanz der „Ball“ Klasse zu tun hatte

und dann anhängen an das Wörterbuch macht es JSON serialisierbar, aber es macht es so, dass, wenn ich in "Bearbeitungsmodus" gehe ich kann die Methode nicht aufrufen (dh changeSize (Name)), weil es gerade ist ein Wörterbuch und nicht mehr ein "Ball" -Objekt.

Wie mache ich es so, dass ich speichern kann (mit JSON-Modul) und auch die Methoden, die ich habe, zu bearbeiten?

Auch die Art, wie ich bin Speichern/Laden wird wie folgt:

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() 

Dank!

Antwort

1

Letztendlich unterstützt json keine Serialisierung von beliebigen Python-Objekten. Wenn Sie das tun möchten, können Sie sich pickle ansehen.

Alternativ können Sie einen alternativen Konstruktor auf Ihrem Ball erstellen, die es mit Werten aus den dict initialisieren werden:

class Ball(object): 

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

    ... 

Ich kann mit 0 Argumenten aufgerufen werden, um dies unter der Annahme, dass der Ball Konstruktor geschrieben habe - Sie müssen möglicherweise den Code ändern, wenn das nicht der Fall ist, oder wenn __init__ etwas "Phantasie" (jenseits Einstellung json Serialisierung Attribute). Ein Weg, um die Forderung der Argumente von __init__ ist __new__ zu verwenden, um die Instanz zu erstellen und dann füllen Sie einfach die Mitglieder durch die Klasse Wörterbuch Aktualisierung:

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) 

Diese beiden Werke in Python2.x und 3.x.

+0

Der 'Ball'-Konstruktor benötigt mindestens einen Namen (aber es wird im Programm aufgefordert, damit es passiert). Willst du damit sagen, dass ich im Prinzip dasselbe mache, was ich bereits mit "Pickle" gemacht habe, dass es funktionieren würde? Ich weiß, dass es weniger sicher ist, und deshalb habe ich versucht, den JSon-Weg zu lernen. Auch, wenn ich mit "Json" fortfahre, könnten Sie mir eine schnelle Erklärung geben, warum Sie einen 'Dekorateur' verwenden? Ich habe kein großes Verständnis von ihnen. Danke vielmals! – AmericanMade

+0

@AmericanMade - Sie könnten 'b = cls (dictionary.get ('name'))' oder etwas ähnliches tun. Re: 'pickle' - Es gibt definitiv Sicherheitsprobleme dort. Nimm niemals etwas auf, wenn du es nicht komplett vertraust. Was das '@ classmethod' betrifft, so macht es das nur so, dass das in' from_json', 'cls' die _class_ ist und keine Instanz der Klasse. – mgilson

Verwandte Themen