首页 > 解决方案 > Pybind11, how to invoke the __repr__ of an object within a std::vector?

问题描述

I'm binding a type my_type

py::class_<my_type, std::shared_ptr<my_type>>(m, "MyType")
        .def("__repr__", [](const my_type& o){return fmt::format("MyType: {}", o);});

as well as a std::vector with

py::bind_vector<std::vector<my_type>>(m, "MyTypeVector");

How can/should I declare MyTypeVector's __repr__ method here if I want its output to be a sequence of MyType.__repr__ for each object in the container?

标签: pybind11

解决方案


JesseC 帮了很多忙,但是有人指出了这种方法的一个弱点:它强制类定义自己的 operator<<,或者程序员在绑定中定义它(如果类已经定义了一个操作符,这是一个问题<<,但与他或她想要的__repr__输出不匹配)。核心库不需要意识到它正在被绑定,因此不应该被迫实现这样的方法。为此,可以将 std::vector 上的 operator<< 修改为:

template<class T>
inline std::string vector_repr(const std::vector<T>& v){
    std::ostringstream out;
    out << "Vector[";

    auto py_vector = py::cast(v);
    const auto separator = ", ";
    const auto* sep = "";

    for( auto obj : py_vector ){
        out << sep << obj.attr("__repr__")();
        sep = separator;
    }
    out << "]";

    return out.str();
}

连同绑定

py::bind_vector<MyTypeVector>(m, "MyTypeVector")
    .def("__repr__", [](const MyTypeVector& v){
             return vector_repr(v);
});

推荐阅读