复制 boost.python 对象

发布于 2024-10-12 13:12:35 字数 369 浏览 3 评论 0原文

我有一些 boost python 类,我在 python 中实例化它们。我想复制它们。所以,如果我有

p = Bernoulli(0.5)

我想做的

q = Bernoulli(p)

但是如果我不知道 p 的类型怎么办?我尝试这样做:

q = copy.deepcopy(p)

但 python 说它无法 pickle p。

我唯一的解决方案是将clone()函数添加到伯努利接口吗?或者我可以以某种方式自动生成该方法吗? copy.deepcopy 可以与 Boost.python 对象一起使用吗?

I have some boost python classes, which I instantiate in python. I want to copy them. So, if I have

p = Bernoulli(0.5)

I want to do

q = Bernoulli(p)

But what if I don't know p's type? I tried to do this:

q = copy.deepcopy(p)

but python said it couldn't pickle p.

Is my only solution to add a clone() function to the interface of Bernoulli? Or can I have that method automatically generated somehow? Can copy.deepcopy be made to work with Boost.python objects?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

时光清浅 2024-10-19 13:12:35

来自 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 & >())

From 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;
}

To use it:

class_<foo>(foo)
   .def("__copy__", &generic__copy__< foo >)
   .def("__deepcopy__", &generic__deepcopy__< foo >)
   .def(init< const foo & >())
行至春深 2024-10-19 13:12:35

对于复制,您可以实现 __copy__ 和 __deepcopy__ 特殊方法(其中之一可以仅包装复制构造函数,具体取决于类的 C++ 复制语义),或者添加pickling 支持copy 模块将使用特殊的复制方法(如果可用),否则将使用 pickling 方法。

下面是使用复制构造函数实现 __copy__ 的示例:

template<typename T> const T copyObject(const T& v) { return v; }
boost::python::class_<C>("C").def("__copy__", copyObject<C>);

For copying, you can either implement the __copy__ and __deepcopy__ special methods (one of them could just wrap the copy constructor, depending on the C++ copy semantics of the class), or add pickling support. The copy module will use the special copying methods if they are available and the pickling methods otherwise.

Here is an example for using the copy constructor to implement __copy__:

template<typename T> const T copyObject(const T& v) { return v; }
boost::python::class_<C>("C").def("__copy__", copyObject<C>);
神爱温柔 2024-10-19 13:12:35

是的,您可以通过在对象上实现 __setstate__ 和 __getstate__ 方法来使 boost::python 对象可深度复制(也可选取)。

基本上, __getstate__ 应该返回一个表示对象内部状态的(python)对象,而 __setstate__ 显然接受所述对象并更新对象的状态。

如果您的对象采用 __init__ 参数,您还应该考虑实现 __getinitargs__

有关更多信息,请参阅 Python 文档

Yes, you can make boost::python objects deep-copyable (and also pickable) by implementing the __setstate__ and __getstate__ methods on your object.

Basically, __getstate__ should return an (python) object that represents the internal state of your object, while __setstate__ obviously accepts said object and updates the state of your object.

If your object takes arguments for __init__, you should also look at implementing __getinitargs__.

See the Python docs for more information.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文