代码之家  ›  专栏  ›  技术社区  ›  mandrake

python-如何通过引用返回?

  •  11
  • mandrake  · 技术社区  · 15 年前

    我使用Boost .python从C++类创建Python模块。我在参考资料方面遇到了问题。

    在下面的情况下,我有一个类foo,它带有重载的get方法,这些方法可以通过值或引用返回。

    一旦我对签名进行typedefed,就很容易指定应该使用返回值。但我认为也可以通过使用 return_value_policy . 然而,使用似乎合适的( doc ; return_value_policy<reference_existing_object> 似乎不起作用。

    我误解它的作用了吗?

    struct Foo {
        Foo(float x) { _x = x; }
        float& get() { return _x; }
        float  get() const { return _x; }
    private:
        float _x;
    };
    
    // Wrapper code
    BOOST_PYTHON_MODULE(my_module)
    {
        using namespace boost::python;
        typedef float (Foo::*get_by_value)() const;
        typedef float& (Foo::*get_by_ref)();
    
        class_<Foo>("Foo", init<float>())
            .def("get", get_by_value(&Foo::get))
            .def("get_ref", get_by_ref(&Foo::get),
                return_value_policy<reference_existing_object>())//Doesn't work
            ;
    }
    

    注:我知道引用现有对象而不进行终身管理是很危险的。

    更新:
    它似乎适用于对象,但不适用于基本数据类型。
    以这个修改过的例子为例:

    struct Foo {
        Foo(float x) { _x = x; }
        float& get() { return _x; }
        float  get() const { return _x; }
        void set( float f ){ _x = f;}
        Foo& self(){return *this;}
    private:
        float _x;
    };
    
    // Wrapper code
    using namespace boost::python;
    BOOST_PYTHON_MODULE(my_module)
    {
        typedef float (Foo::*get_by_value)() const;
    
        class_<Foo>("Foo", init<float>())
            .def("get", get_by_value(&Foo::get))
            .def("get_self", &Foo::self,
                return_value_policy<reference_existing_object>())
            .def("set", &Foo::set);
            ;
    }
    

    在测试中得出预期结果:

    >>> foo1 = Foo(123)
    >>> foo1.get()
    123.0
    >>> foo2 = foo1.get_self()
    >>> foo2.set(1)
    >>> foo1.get()
    1.0
    >>> id(foo1) == id(foo2)
    False
    
    4 回复  |  直到 7 年前
        1
  •  7
  •   gd1    7 年前

    在python中,有 恒定类型 . 不可变类型的值不能更改。内置不可变类型的例子有int、float和str。

    说了这句话,你就不能随心所欲了 boost::python 因为python本身不允许更改函数返回的浮点值。

    第二个示例显示了一个解决方案,另一个解决方案是创建薄包装并公开:

    void Foo_set_x(Foo& self, float value) {
        self.get() = value;
    }
    
    class_<Foo>("Foo", init<float>())
        ...
        .def("set", &Foo_set_x);
    ;
    

    这是一个更好的解决方案,而不是改变原来的C++类。

        2
  •  2
  •   Charles    8 年前

    我想你想要 return internal reference 相反。我以前也用过类似的方法。

    编辑: Latest doc

        3
  •  0
  •   Lennart Regebro    15 年前

    我对boost.python不太了解,所以我可能会误解这个问题,在这种情况下,这是完全没有帮助的。但这里可以说:

    在python中,不能在按引用返回和按值返回之间进行选择,这在python中是没有意义的。我发现最容易把它看作是所有被引用处理的事情。

    你只有对象,你有这些对象的名称。所以

    foo = "ryiuy"
    

    创建字符串对象“ryiuy”,然后让您引用名为“foo”的字符串对象。所以在python中,当您通过某个对象时,您会通过该对象。没有“值”,因此无法传递值。但同样,它也是一个有效的观点,即也没有引用,只有对象及其名称。

    因此,我猜答案是,当您在C中得到一个引用时,您需要将一个引用传递给引用到Python中的对象。当您在C中得到一个值时,您需要将一个对您从该值创建的对象的引用传递给python。

        4
  •  0
  •   Ben    15 年前

    您确信C++对象正在被复制吗?每次你都会得到一个新的Python对象,但它引用同一个C++对象。如何确定对象已被复制?