Ecco alcuni metodi aggiuntivi. Nessuna è di applicabilità generale come lo è accepted answer, ma se la classe soddisfa alcuni (semplici) requisiti, è possibile rendere più facile il decapaggio sui propri utenti rendendo selezionabili le istanze stesse (non le versioni avvolte). Queste tecniche sono tutte utilizzate dallo LSST afw package.
noti che quando deserializzazione utilizzando la coppia __getstate__
/__setstate__
, sarà non essere chiamato il metodo __init__
, il che significa che se non si sta attenti, avrete un oggetto che non si può fare nulla con (se continui a ricevere NotImplementedError: Wrong number or type of arguments for overloaded function
, questa è una possibilità). Questo ci spinge a usare __reduce__
(o è possibile chiamare __init__
da __setstate__
).
Se siete classe SWIG-ing Foo
che prende argomenti del costruttore che si ha accesso dall'istanza (ad esempio, via di accesso), aggiungere il seguente alla vostra interfaccia (.i
) File:
%extend Foo {
%pythoncode {
def __reduce__(self):
# Requires matching constructor: __init__(foo, bar)
args = self.getFoo(), self.getBar()
return self.__class__, args
}
}
Se è possibile creare il vostro oggetto con un costruttore di default e poi manipolarlo per ritrovare il suo stato precedente, usare qualcosa di simile a questo:
%extend Foo {
%pythoncode {
def __getstate__(self):
args = self.getFoo(), self.getBar()
return args
def __setstate__(self, state):
# Requires empty constructor: __init__()
self.__init__()
foo, bar = state
self.setFoo(foo)
self.setBar(bar)
}
}
in alternativa, se la classe può fare una serializzazione dei dati binari a/dalla memoria (ad esempio, ., Qualche rappresentazione in memoria del proprio formato su disco):
%include "cdata.i"
%extend Foo {
%pythoncode {
def __reduce__(self):
s = Serializer()
self.serialize(s)
size = s.getLength()
data = cdata(s.getData(), size)
return unreduceFoo, (data, size)
}
}
%pythoncode {
def unreduceFoo(data, size):
s = Serializer(size)
memmove(s.getData(), data)
return Foo(s)
}
Infine, se si sta utilizzando boost::serialization
, utilizzare questo frammento da Sogo Mineo:
%{
#include <boost/serialization/serialization.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <sstream>
%}
%include "std_string.i"
%define %boost_picklable(cls...)
%extend cls {
std::string __getstate__()
{
std::stringstream ss;
boost::archive::binary_oarchive ar(ss);
ar << *($self);
return ss.str();
}
void __setstate_internal(std::string const& sState)
{
std::stringstream ss(sState);
boost::archive::binary_iarchive ar(ss);
ar >> *($self);
}
%pythoncode %{
def __setstate__(self, sState):
self.__init__()
self.__setstate_internal(sState)
%}
}
%enddef
%boost_picklable(Foo)
E forse metaclasse può essere utilizzato Qui. – alexanderkuk
Nel caso si sia interessati alla valutazione parallela con mpi4py, avevo bisogno di implementare ulteriormente la soluzione suggerita [qui] (http://stackoverflow.com/questions/1816958/cant-pickle-type-instancemethod-when-using-pythons- multiprocessing-pool-ma) per farlo funzionare con i metodi di istanza della classe (wrapping) –
@FredSchoen: il serializzatore 'dill' può essere utilizzato con' mpi4py'. Basta impostare il serializzatore su 'dill' invece di' pickle'. Vedi: http://stackoverflow.com/questions/21779541/mpi4py-replace-built-in-serialization –