Pybind11,如何调用 std::vector 中对象的 __repr__ ?

pol*_*iz4 2 pybind11

我正在绑定类型 my_type

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

以及 std::vector<my_type> 与

py::bind_vector<std::vector<my_type>>(m, "MyTypeVector");
Run Code Online (Sandbox Code Playgroud)

如果我希望它的输出是容器中每个对象__repr__的序列,我可以/应该如何在这里声明 MyTypeVector 的方法?MyType.__repr__

Jes*_*e C 5

其实很简单。py::bind_vector只是一个包装器class_,因此您可以向其中添加方法,就像将它们添加到普通类中一样。

在你的情况下你可以这样做

py::bind_vector<std::vector<my_type>>(m, "MyTypeVector")
  .def("__repr__", [](const std::vector<my_type>& v) {// generate your string here;});
Run Code Online (Sandbox Code Playgroud)

因此,为了制作字符串表示形式,我通常在 C++ 类中定义toString方法和运算符。<<

class BadData
{
// lots of stuff going on and removed here
    virtual void
    putMembers(std::ostream& out) const
    {
      out << "msg=" << >msg;
      out << ", ";
      out << "stack=" << stack;
    }

    virtual std::string
    toString() const
    {
      std::ostringstream out;
      out << "BadData(";
      putMembers(out);
      out << ")";
      return out.str();
    }
}

inline
std::ostream &operator<<(std::ostream& stream, const BadData &item)
{
  stream << item.toString();
  return stream;
}

Run Code Online (Sandbox Code Playgroud)

我们还为 stl 集合定义了operator<<

template<class T> inline
std::ostream& operator << (std::ostream& os, const std::vector<T>& v)
{
  std::ostringstream out;
  out << "Vector[";
  if (v.size() > 0) {
    for (auto ii = v.cbegin(); ii != v.cend() -1 ; ++ii) {
      out << *ii << ", ";
    }
    out << v.back();
  }
  out << "]";
  os << out.str();
  return os;
}
Run Code Online (Sandbox Code Playgroud)

因此,一旦定义了所有这些运算符,您的__repr__方法就可以看起来像

.def("__repr__", [](const std::vector<my_type>& v) {
    std::stringstream stream;
    stream << v;
    return stream.str(); 
})
Run Code Online (Sandbox Code Playgroud)

或者在您的自定义类的情况下,例如

.def("__repr__", &::my_type::toString)
Run Code Online (Sandbox Code Playgroud)