Hi, > The docs regarding the mutable copying problem are very misleading. > Following Python [1] and Boost [2] scripts do not produce the same results: > > > [1] > b = a = [] > c = list(a) > a.append("s1") > print a.count("s1"), b.count("s1"), c.count("s1") #prints 1 1 0 > > [2] > list a, b, c; > b = a; > c = list(a); > a.append("s1"); > list d = extract<list>(a); > printf("%i %i %i %i\n", a.count("s1"), b.count("s1"), c.count("s1"), > d.count("s1")); //prints 1 1 1 1 > > In [2] expected was 1 1 0 1 according to Pythonic behaviour (it states > in docs that such behaviour is mimicked). This is in conflict with > example provided in the tutorial.
Ok, so it seems behaviour is different when dealing with boost::python::object vs PyObject* as constructor arguments. Using extract<> to modify mutable objects is only necessary when dealing with PyObject*: // boost_dict.cpp /* build cmdline: /apps/local/gcc/4.6.1/bin/g++ -g -Wall -R /apps/local/gcc/4.6.1/lib/ -R /var/tmp/boost/gcc/boost_1_47_0/stage/gcc-4.6.1/py2.7/boost/1.47.0/lib/ -L /var/tmp/boost/gcc/boost_1_47_0/stage/gcc-4.6.1/py2.7/boost/1.47.0/lib/ -I /var/tmp/boost/gcc/boost_1_47_0/ -I /apps/local/gcc/4.6.1/include/python2.7/ -L /apps/local/gcc/4.6.1/lib boost_dict.cpp -lboost_python -lrt -lpython2.7 */ #include <boost/python.hpp> #include <iostream> namespace bp = boost::python; int main(void) { // otherwise we core dump Py_Initialize(); bp::object value(1); std::cout << "arg is bp::dict:" << std::endl; { bp::dict d1, d2, d3; d2 = d1; d3 = bp::dict(d1); d1["k1"] = value; bp::dict d4 = bp::extract<bp::dict>(d1); std::cout << d1.has_key("k1") << " " << d2.has_key("k1") << " " << d3.has_key("k1") << " " << d4.has_key("k1") << std::endl; } std::cout << std::endl; std::cout << "arg is bp::handle<(PyObj*)" << std::endl; { bp::dict d1, d2, d3; // must use a handle to feed PyObj* to bp::objects bp::handle<> dict_pyobj_handle(d1.ptr()); // Note: no operator= for handle<> d2 = bp::dict(dict_pyobj_handle); d3 = bp::dict(dict_pyobj_handle); d1["k1"] = value; bp::dict d4 = bp::extract<bp::dict>(d1.ptr()); std::cout << d1.has_key("k1") << " " << d2.has_key("k1") << " " << d3.has_key("k1") << " " << d4.has_key("k1") << std::endl; } Py_Finalize(); return 0; } $ ./a.out arg is bp::dict: 1 1 1 1 arg is bp::handle<(PyObj*) 1 0 0 1 So I think the tutorial example (if that's what you meant?) " C++: dict d(x.attr("__dict__")); // copies x.__dict__ d['whatever'] = 3; // modifies the copy " is pretty subtle, as - if I understand correctly - this - retrieves an attribute proxy from x - that returns the bp::object-wrapped __dict__ attribute (which copies the original PyObject* __dict__) - constructs d from this new bp::object (which increases the refcount but doesn't make another copy) and the assignment operates on this new bp::object. Regards Holger Landesbank Baden-Wuerttemberg Anstalt des oeffentlichen Rechts Hauptsitze: Stuttgart, Karlsruhe, Mannheim, Mainz HRA 12704 Amtsgericht Stuttgart _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig