Ich möchte, dass meine Klasse Save and Load-Funktionen implementiert, die einfach ein Pickle der Klasse ausführen. Aber anscheinend können Sie "Selbst" nicht wie folgt verwenden. Wie kannst du das tun?
Ich könnte das Diktat aufgreifen , aber dann könnte ich die Klasse später nicht mehr ändern.
7
ausgezeichneter Titel, + 1'ed
pcko1
Antworten:
44
Das habe ich letztendlich getan. Durch das Aktualisieren der __dict__Mittel behalten wir alle neuen Mitgliedsvariablen bei, die ich der Klasse hinzufüge, und aktualisieren nur diejenigen, die vorhanden waren, als das Objekt zuletzt ausgewählt wurde. Es scheint am einfachsten zu sein, wenn der Speicher- und Ladecode in der Klasse selbst beibehalten wird, sodass beim Aufrufen von Code nur ein object.save () ausgeführt wird.
defload(self):
f = open(self.filename, 'rb')
tmp_dict = cPickle.load(f)
f.close()
self.__dict__.update(tmp_dict)
defsave(self):
f = open(self.filename, 'wb')
cPickle.dump(self.__dict__, f, 2)
f.close()
Dies ist ein merge. Sie sollten anrufen, self.__dict__.clear()bevor Sie anrufenself.__dict__.update(..)
deepelement
1
Gibt es einen bestimmten Grund, warum Sie keine "with" -Anweisungen verwenden?
Ekelhaft
1
Warum verwenden Sie den 3. Parameter = 2?
Agustin Barrachina
Diese Lösung hat einige nette Eigenschaften, aber einen wichtigen Nachteil: Sie müssen ein Objekt erstellen, bevor Sie die Ladefunktion aufrufen, und Sie haben möglicherweise keine Option, den Konstruktor mit gültigen Daten aufzurufen. Das Erstellen einer Factory-Klassenmethode ist daher sinnvoller.
Emem
26
Der Dump-Teil sollte wie vorgeschlagen funktionieren. Für den Ladeteil können Sie eine @ classmethod definieren , die eine Instanz aus einer bestimmten Datei lädt und zurückgibt.
Was Sie also sagen, ist mit der Klasse Foo, Instanz foo Ich kann foo.Save () machen, aber ich kann nicht foo.Load () Ich müsste foo = foo.Load () - (Klassenmethoden können mit aufgerufen werden ein
7
Es ist durchaus sinnvoll, dass Sie foo = Foo.load () und nicht foo = Foo (); foo.load () verwenden. Wenn Foo beispielsweise einige Variablen hat, die an den Init übergeben werden MÜSSEN, müssen Sie sie für foo = Foo () nachholen. oder wenn der Init einige schwere Berechnungen von in der Instanz gespeicherten Variablen durchführt, wäre dies umsonst.
Ofri Raviv
1
Dies funktioniert, ursprünglich hatte ich foo = Foo ('somefilename') und Foo hat seine Daten selbst geladen. Jetzt mache ich a: foo = Foo.Load ('somefilename') Wenn ich die Definition von Foo ändere, kann ich die neuen Funktionen / Mitglieder in der mit Pickle geladenen foo-Instanz weiterhin verwenden.
8
Wenn Sie möchten, dass sich Ihre Klasse von einer gespeicherten Gurke selbst aktualisiert, müssen Sie so ziemlich alles verwenden __dict__.update, wie Sie es in Ihrer eigenen Antwort getan haben. Es ist jedoch so, als würde eine Katze ihren Schwanz jagen ... während Sie die Instanz bitten, sich im Wesentlichen auf den vorherigen Zustand zurückzusetzen.
Ihre Antwort hat eine leichte Änderung. Sie können tatsächlich einlegen self.
Ich habe loadsund benutztdumps anstelle von loadund verwendet, dumpweil ich wollte, dass die Gurke in einer Zeichenfolge gespeichert wird. Das Verwenden von loadund dumpzu einer Datei funktioniert auch. Und tatsächlich kann ich dilleine Klasseninstanz zur späteren Verwendung in eine Datei einfügen ... selbst wenn die Klasse interaktiv definiert ist. Fortsetzung von oben ...
>>> withopen('self.pik', 'w') as f:
... dill.dump(t, f)
... >>>
dann anhalten und neu starten ...
Python 2.7.10 (default, May 252015, 13:16:30)
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
Type "help", "copyright", "credits"or"license"for more information.
>>> import dill
>>> withopen('self.pik', 'r') as f:
... t = dill.load(f)
... >>> t.x
1>>> print dill.source.getsource(t.__class__)
classThing(object):defsave(self):return dill.dumps(self)
defload(self, obj):
self.__dict__.update(dill.loads(obj).__dict__)
>>>
In den Dokumenten finden Sie ein Beispiel für das Auswählen einer Instanz . (Suchen Sie nach dem Beispiel "TextReader"). Die Idee ist , zu definieren __getstate__und __setstate__Methoden, mit denen Sie definieren , welche Daten Bedürfnisse gebeizt werden, und wie diese Daten zu verwenden , um Wieder instantiate das Objekt.
Dies löst das Problem nicht, da Sie in der Load-Funktion der Klasse immer noch nicht self = cPickle.load (f) aufrufen können, um die Klasse mit den geladenen Daten zu füllen. Oder natürlich kann ich die Klassendaten selbst auswählen, aber ich versuche zu vermeiden, den gesamten Code zu schreiben und gezwungen zu sein, ihn zu aktualisieren, wenn sich die Variablen der Klassenmitglieder ändern.
0
So habe ich es gemacht. Der Vorteil ist, dass Sie kein neues Objekt erstellen müssen. Sie können es einfach direkt laden.
defsave(self):withopen(self.filename, 'wb') as f:
pickle.dump(self, f)
@classmethoddefload(cls, filename):withopen(filename, 'rb') as f:
return pickle.load(f)
Wie man es benutzt:
class_object.save()
filename = class_object.filename
del class_object
class_object = ClassName.load(filename)
Antworten:
Das habe ich letztendlich getan. Durch das Aktualisieren der
__dict__
Mittel behalten wir alle neuen Mitgliedsvariablen bei, die ich der Klasse hinzufüge, und aktualisieren nur diejenigen, die vorhanden waren, als das Objekt zuletzt ausgewählt wurde. Es scheint am einfachsten zu sein, wenn der Speicher- und Ladecode in der Klasse selbst beibehalten wird, sodass beim Aufrufen von Code nur ein object.save () ausgeführt wird.def load(self): f = open(self.filename, 'rb') tmp_dict = cPickle.load(f) f.close() self.__dict__.update(tmp_dict) def save(self): f = open(self.filename, 'wb') cPickle.dump(self.__dict__, f, 2) f.close()
quelle
load
undsave
in Kleinbuchstaben python.org/dev/peps/pep-0008/#function-namesmerge
. Sie sollten anrufen,self.__dict__.clear()
bevor Sie anrufenself.__dict__.update(..)
Der Dump-Teil sollte wie vorgeschlagen funktionieren. Für den Ladeteil können Sie eine @ classmethod definieren , die eine Instanz aus einer bestimmten Datei lädt und zurückgibt.
@classmethod def loader(cls,f): return cPickle.load(f)
dann würde der Anrufer so etwas tun wie:
quelle
Wenn Sie möchten, dass sich Ihre Klasse von einer gespeicherten Gurke selbst aktualisiert, müssen Sie so ziemlich alles verwenden
__dict__.update
, wie Sie es in Ihrer eigenen Antwort getan haben. Es ist jedoch so, als würde eine Katze ihren Schwanz jagen ... während Sie die Instanz bitten, sich im Wesentlichen auf den vorherigen Zustand zurückzusetzen.Ihre Antwort hat eine leichte Änderung. Sie können tatsächlich einlegen
self
.>>> import dill >>> class Thing(object): ... def save(self): ... return dill.dumps(self) ... def load(self, obj): ... self.__dict__.update(dill.loads(obj).__dict__) ... >>> t = Thing() >>> t.x = 1 >>> _t = t.save() >>> t.x = 2 >>> t.x 2 >>> t.load(_t) >>> t.x 1
Ich habe
loads
und benutztdumps
anstelle vonload
und verwendet,dump
weil ich wollte, dass die Gurke in einer Zeichenfolge gespeichert wird. Das Verwenden vonload
unddump
zu einer Datei funktioniert auch. Und tatsächlich kann ichdill
eine Klasseninstanz zur späteren Verwendung in eine Datei einfügen ... selbst wenn die Klasse interaktiv definiert ist. Fortsetzung von oben ...>>> with open('self.pik', 'w') as f: ... dill.dump(t, f) ... >>>
dann anhalten und neu starten ...
Python 2.7.10 (default, May 25 2015, 13:16:30) [GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import dill >>> with open('self.pik', 'r') as f: ... t = dill.load(f) ... >>> t.x 1 >>> print dill.source.getsource(t.__class__) class Thing(object): def save(self): return dill.dumps(self) def load(self, obj): self.__dict__.update(dill.loads(obj).__dict__) >>>
Ich verwende
dill
, das hier verfügbar ist: https://github.com/uqfoundationquelle
In den Dokumenten finden Sie ein Beispiel für das Auswählen einer Instanz . (Suchen Sie nach dem Beispiel "TextReader"). Die Idee ist , zu definieren
__getstate__
und__setstate__
Methoden, mit denen Sie definieren , welche Daten Bedürfnisse gebeizt werden, und wie diese Daten zu verwenden , um Wieder instantiate das Objekt.quelle
So habe ich es gemacht. Der Vorteil ist, dass Sie kein neues Objekt erstellen müssen. Sie können es einfach direkt laden.
def save(self): with open(self.filename, 'wb') as f: pickle.dump(self, f) @classmethod def load(cls, filename): with open(filename, 'rb') as f: return pickle.load(f)
Wie man es benutzt:
class_object.save() filename = class_object.filename del class_object class_object = ClassName.load(filename)
quelle