Éstos son algunos métodos adicionales. Ninguno tiene una aplicabilidad tan general como el accepted answer, pero si su clase cumple con algunos requisitos (simples), entonces puede facilitar el decapado a sus usuarios haciendo que las instancias mismas (no versiones envueltas) se puedan seleccionar. Estas técnicas son todas usadas por el LSST afw package.
Tenga en cuenta que cuando deserialiación utilizando el par __getstate__
/__setstate__
, el método __init__
se no ser llamado, lo que significa que a menos que usted tiene cuidado, usted tiene un objeto que no se puede hacer nada con (si sigues recibiendo NotImplementedError: Wrong number or type of arguments for overloaded function
, esta es una posibilidad). Esto nos lleva a utilizar __reduce__
(o puede llamar al __init__
desde __setstate__
).
Si eres de clase TRAGO-ción Foo
que tiene argumentos de constructor que tiene acceso a partir de la instancia (por ejemplo, a través de descriptores de acceso), añada lo siguiente a su interfaz (.i
) Archivo:
%extend Foo {
%pythoncode {
def __reduce__(self):
# Requires matching constructor: __init__(foo, bar)
args = self.getFoo(), self.getBar()
return self.__class__, args
}
}
Si usted puede crear su objeto con un constructor por defecto y luego manipularla para recuperar su estado anterior, usar algo como esto:
%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)
}
}
Alternativamente, si la clase puede hacer una serialización de datos binarios a/desde la memoria (por ejemplo, ., Alguna representación en memoria de su propio formato en 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)
}
Por último, si usted está utilizando boost::serialization
, utilice este fragmento por 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)
Y tal metaclase se puede utilizar aquí. – alexanderkuk
En caso de que uno esté interesado en la evaluación paralela con mpi4py, necesitaba implementar adicionalmente la solución sugerida [aquí] (http://stackoverflow.com/questions/1816958/cant-pickle-type-instancemethod-when-using-pythons- multiprocesamiento-pool-ma) para hacer que funcione con los métodos de instancia de la clase (envuelta) –
@FredSchoen: el serializador 'eneldo' se puede usar con' mpi4py'. Simplemente configure el serializador para 'eneldo' en lugar de 'salmuera'. Ver: http://stackoverflow.com/questions/21779541/mpi4py-replace-built-in-serialization –