Обработка нескольких типизированных аргументов в pybind11 - PullRequest
0 голосов
/ 17 апреля 2019

У меня есть функция, которая принимает четыре аргумента.Два из этих аргументов могут независимо быть либо int, вектором int, либо вектором вектора int (в результате получается 3 * 3 = 9 возможных комбинаций).Сейчас я пишу привязку Python для этой функции, и вместо того, чтобы писать несколько перегрузок, я хотел бы написать одно определение, охватывающее все эти возможные комбинации, используя динамическую проверку типов.

Я думаю, что это можно сделать, объявив аргументы как py :: handle, а затем используя py::instance и py::cast.Поэтому я попробовал что-то вроде этого

    m.def("pad",
          [](const ArrayBodyPtr& array, py::handle pad_width, const std::string& mode, py::handle constant_values) {
              PadMode pad_mode{};
              if (mode == "constant") {
                  pad_mode = PadMode::constant;
              } else {
                  throw py::value_error{"Currently only `constant` padding mode is supported"};
              }

              // pad_width : int64_t
              if (py::isinstance<int64_t>(pad_width)) {
                  casted_pad_width = py::cast<int64_t>(pad_width);
              }
              // pad_width : vector of int64_t
              if (py::isinstance<std::vector<int64_t>>(pad_width)){
                  casted_pad_width = py::cast<std::vector<int64_t>>(pad_width);
              }
              // pad_width : vector of vector of int64_t
              if (py::isinstance<std::vector<std::vector<<int64_t>>>(pad_width)){
                  casted_pad_width = py::cast<std::vector<std::vector<<int64_t>>>(pad_width);
              }
              // constant_values : Scalar
              if (py::isinstance<Scalar>(constant_values)) {
                  casted_constant_values = py::cast<Scalar>(constant_values);
              }
              // constant_values : vector of Scalar
              if (py::isinstance<std::vector<Scalar>>(constant_values)){
                  casted_constant_values = py::cast<std::vector<Scalar>>(constant_values);
              }
              // constant_values : vector of vector of Scalar
              if (py::isinstance<std::vector<std::vector<<Scalar>>>(constant_values)){
                  casted_constant_values = py::cast<std::vector<std::vector<<Scalar>>>(constant_values);
              }
              return MoveArrayBody(Pad(Array{array}, casted_pad_width, pad_mode, casted_constant_values));
          },
          py::arg("array"),
          py::arg("pad_width"),
          py::arg("mode"),
          py::arg("constant_values"));

Но сейчас я не знаю, каким типом инициализировать переменные casted_pad_width и casted_constant_values.Если я инициализирую их в каждом операторе if, они становятся локальными переменными и недоступны в операторе end.Если я напишу MoveArrayBody(Pad(Array{array}, casted_pad_width, pad_mode, casted_constant_values)) в каждом блоке if, тогда цель написания чистой реализации будет потеряна.Итак, что будет правильным путем?

(Кроме того, это функция pad, используемая для заполнения матриц)

...