Voglio che la mia classe implementa funzioni di salvataggio e caricamento che fanno semplicemente un pickle della classe. Ma a quanto pare non puoi usare 'self' nel modo seguente. Come puoi fare questo?Come metterti?
risposta
Questo è quello che ho finito per fare. L'aggiornamento del __dict__
significa che manterremo eventuali nuove variabili membro che aggiungo alla classe e aggiorno solo quelle che erano presenti quando l'oggetto è stato sottoposto all'ultimo sottaceto. Sembra il più semplice pur mantenendo il codice di salvataggio e caricamento all'interno della classe stessa, quindi chiamare il codice esegue semplicemente object.save().
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()
Un nitpick PEP8 minore - le funzioni dovrebbero essere denominate 'load' e' save' in https://www.python.org/dev/peps/pep-0008/#function-names –
in caratteri minuscoli ... – danijar
Questo è un 'unione'. Dovresti chiamare 'self .__ dict __. Clear()' prima di chiamare 'self .__ dict __. Update (..)' – deepelement
C'è un esempio di come decollare un'istanza here, in the docs. (Cerca in basso per l'esempio "TextReader"). L'idea è di definire i metodi __getstate__
e __setstate__
, che consentono di definire quali dati devono essere decapitati e come utilizzare tali dati per riattivare l'oggetto.
Questo non risolve il problema perché non è ancora possibile richiamare la funzione di caricamento della classe self = cPickle.load (f) per riempire la classe con i dati caricati. Ovviamente posso mettere a picco i dati della classe stessa, ma sto cercando di evitare di scrivere tutto quel codice e di essere costretto ad aggiornarlo quando le variabili dei membri della classe cambiano. – Mark
La parte di scarico dovrebbe funzionare come suggerito. per la parte di caricamento, è possibile definire un @classmethod che carica un'istanza da un determinato file e la restituisce.
@classmethod
def loader(cls,f):
return cPickle.load(f)
poi il chiamante potrebbe fare qualcosa di simile:
class_instance = ClassName.loader(f)
Quindi quello che stai dicendo è con la classe Foo, instance foo Posso fare foo.Save() ma non posso fare foo.Load() Dovrei fare foo = foo.Load() - (i metodi di classe possono essere chiamati con un'istanza o nome di classe) – Mark
È perfettamente logico utilizzare foo = Foo.load(), e non foo = Foo(); foo.load(). per esempio, se Foo ha alcune variabili che DEVONO essere passate in init, dovresti crearle per foo = Foo(); o se l'init fa alcuni calcoli pesanti di variabili memorizzate nell'istanza, sarebbe per niente. –
Questo funziona, originariamente avevo foo = (nomefile ') E Foo stava facendo il proprio caricamento dei suoi dati. Ora faccio un: foo = Foo.Load ('somefilename') Se modifico la definizione di Foo, posso ancora usare le nuove funzioni/membri nell'istanza di pickle caricato da foo. – Mark
ne dite di scrivere una classe chiamata Serializable che implementare discarica e caricare e rendere il vostro ereditare classe da esso?
Se si vuole avere la classe per sé l'aggiornamento da una salamoia salvato ... è praticamente necessario utilizzare __dict__.update
, come avete nella vostra risposta. È un po 'come un gatto che insegue la coda, comunque ... come stai chiedendo all'istanza di "resettarsi" essenzialmente con lo stato precedente.
C'è un piccolo ritocco per la tua risposta. Si può in realtà sottaceto 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
Ho usato loads
e dumps
invece di load
e dump
perché volevo la salamoia per salvare in una stringa. L'utilizzo di load
e dump
in un file funziona anche. E, in realtà, posso usare dill
per decapitare un'istanza di classe in un file, per un uso successivo ... anche se la classe è definita in modo interattivo. Proseguendo dall'alto ...
>>> with open('self.pik', 'w') as f:
... dill.dump(t, f)
...
>>>
quindi arrestare e riavviare ...
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__)
>>>
sto usando dill
, che è disponibile qui: https://github.com/uqfoundation
ho potuto serializzazione __dict__, ma poi Non sarei in grado di modificare successivamente la classe. – Mark