Копирование объекта boost.python - PullRequest
4 голосов
/ 15 января 2011

У меня есть несколько улучшенных классов Python, которые я создаю в Python. Я хочу скопировать их. Итак, если у меня есть

p = Bernoulli(0.5)

хочу сделать

q = Bernoulli(p)

Но что, если я не знаю тип p? Я пытался сделать это:

q = copy.deepcopy(p)

но питон сказал, что не может засолить р.

Является ли мое единственное решение добавить функцию clone () в интерфейс Бернулли? Или я могу автоматически создать этот метод? Можно ли сделать copy.deepcopy для работы с объектами Boost.python?

Ответы [ 3 ]

4 голосов
/ 16 января 2011

С http://mail.python.org/pipermail/cplusplus-sig/2009-May/014505.html

#define PYTHON_ERROR(TYPE, REASON) \
{ \
    PyErr_SetString(TYPE, REASON); \
    throw bp::error_already_set(); \
}

template<class T>
inline PyObject * managingPyObject(T *p)
{
    return typename bp::manage_new_object::apply<T *>::type()(p);
}

template<class Copyable>
bp::object
generic__copy__(bp::object copyable)
{
    Copyable *newCopyable(new Copyable(bp::extract<const Copyable
&>(copyable)));
    bp::object
result(bp::detail::new_reference(managingPyObject(newCopyable)));

    bp::extract<bp::dict>(result.attr("__dict__"))().update(
        copyable.attr("__dict__"));

    return result;
}

template<class Copyable>
bp::object
generic__deepcopy__(bp::object copyable, bp::dict memo)
{
    bp::object copyMod = bp::import("copy");
    bp::object deepcopy = copyMod.attr("deepcopy");

    Copyable *newCopyable(new Copyable(bp::extract<const Copyable
&>(copyable)));
    bp::object
result(bp::detail::new_reference(managingPyObject(newCopyable)));

    // HACK: copyableId shall be the same as the result of id(copyable)
in Python -
    // please tell me that there is a better way! (and which ;-p)
    int copyableId = (int)(copyable.ptr());
    memo[copyableId] = result;

    bp::extract<bp::dict>(result.attr("__dict__"))().update(
        deepcopy(bp::extract<bp::dict>(copyable.attr("__dict__"))(),
memo));

    return result;
}

Чтобы использовать это:

class_<foo>(foo)
   .def("__copy__", &generic__copy__< foo >)
   .def("__deepcopy__", &generic__deepcopy__< foo >)
   .def(init< const foo & >())
2 голосов
/ 15 января 2011

Для копирования вы можете либо реализовать специальные методы __copy__ и __deepcopy__ (один из них может просто обернуть конструктор копирования, в зависимости от семантики копирования C ++ класса), либо добавить поддержку выбора . Модуль copy будет использовать специальные методы копирования, если они доступны, и методы травления в противном случае.

Вот пример использования конструктора копирования для реализации __copy__:

template<typename T> const T copyObject(const T& v) { return v; }
boost::python::class_<C>("C").def("__copy__", copyObject<C>);
1 голос
/ 15 января 2011

Да, вы можете сделать объекты boost :: python глубоко копируемыми (и также выбираемыми), реализовав методы __setstate__ и __getstate__ для вашего объекта.

По сути, __getstate__ должен возвращать (python) объект, который представляет внутреннее состояние вашего объекта, в то время как __setstate__ явно принимает указанный объект и обновляет состояние вашего объекта.

Если ваш объект принимает аргументы для __init__, вам также следует обратить внимание на реализацию __getinitargs__.

См. Python docs для получения дополнительной информации.

...