4

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

p = Bernoulli(0.5)

我想要做

q = Bernoulli(p)

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

q = copy.deepcopy(p)

但是python说它不能腌制p。

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

4

3 回答 3

4

来自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 & >())
于 2011-01-15T23:19:47.217 回答
2

对于复制,您可以实现__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>);
于 2011-01-14T23:40:59.103 回答
1

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

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

如果你的对象接受参数__init__,你也应该看看实现__getinitargs__

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

于 2011-01-14T23:24:08.660 回答