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<my_type> 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?
JesseC helped a lot, but someone pointed out a weakness in that approach: it forces either the classes to define their own operator<<, or the programmer to define it in the bindings (which is a problem if the class has already defined an operator<<, but doesn't match what he or she wants as their __repr__
output). The core library shouldn't need to be aware that it's getting binded and therefore shouldn't be forced to implement such method.
To that end, one can modify the operator<< on the std::vector to:
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();
}
along with the binding
py::bind_vector<MyTypeVector>(m, "MyTypeVector")
.def("__repr__", [](const MyTypeVector& v){
return vector_repr(v);
});