Вот несколько дополнительных методов. Ни один из них не имеет такой же общей применимости, как принятый ответ , но если ваш класс удовлетворяет некоторым (простым) требованиям, вы можете облегчить процесс засолки для своих пользователей, сделав возможность выбора самих экземпляров (не упакованных версий). Все эти методы используются пакетом LSST afw .
Обратите внимание, что при снятии травления с использованием пары __getstate__
/ __setstate__
метод __init__
будет вызываться , а не , что означает, что если вы не будете осторожны, у вас будет объект, который Вы ничего не можете сделать с (если вы продолжаете получать NotImplementedError: Wrong number or type of arguments for overloaded function
, это возможно). Это заставляет нас использовать __reduce__
(или вы можете позвонить __init__
с __setstate__
).
Если вы SWIG-класс Foo
, который принимает аргументы конструктора, к которым у вас есть доступ из экземпляра (например, через средства доступа), добавьте в файл интерфейса (.i
) следующее:
%extend Foo {
%pythoncode {
def __reduce__(self):
# Requires matching constructor: __init__(foo, bar)
args = self.getFoo(), self.getBar()
return self.__class__, args
}
}
Если вы можете создать свой объект с помощью конструктора по умолчанию, а затем манипулировать им, чтобы восстановить прежнее состояние, используйте что-то вроде этого:
%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)
}
}
В качестве альтернативы, если ваш класс может выполнять сериализацию двоичных данных в / из памяти (например, некоторое представление в памяти вашего собственного формата на диске):
%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)
}
Наконец, если вы используете boost::serialization
, используйте этот фрагмент 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)