テンプレート化されたビジターを使用して、いくつかのクラスの統一されたインターフェイスを定義しています。__str__
メソッドとメソッドを定義する目的で、オブジェクトからクラス名 (参照ドキュメント内の)__repr__
をプログラムで取得したいと考えています。それは可能ですか?"X"
boost::python::class
クラス名を引数としてビジターのコンストラクターに渡すことで簡単に回避できますが、自動的にクラス名を指定する方がエレガントです。
テンプレート化されたビジターを使用して、いくつかのクラスの統一されたインターフェイスを定義しています。__str__
メソッドとメソッドを定義する目的で、オブジェクトからクラス名 (参照ドキュメント内の)__repr__
をプログラムで取得したいと考えています。それは可能ですか?"X"
boost::python::class
クラス名を引数としてビジターのコンストラクターに渡すことで簡単に回避できますが、自動的にクラス名を指定する方がエレガントです。
boost::python::class_
から派生しているため、クラス オブジェクトから属性boost::python::object
を照会できます。__name__
簡単な例を次に示します。
#include <boost/python.hpp>
class X {};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::object x_class = python::class_<X>("X");
// Extract the class' __name__ attribute, printing whatever was passed to
// class_ constructor.
std::cout << boost::python::extract<std::string>(x_class.attr("__name__"))()
<< std::endl;
}
そして出力:
>>> import example
X
このアプローチを拡張するには、派生元の訪問者は次のboost::python::def_visitor
いずれかを行う必要があります。
__str__
and/orをを介して「クラス」名を__repr__
一般的に返す関数として定義 します。boost::python::object
o.__class__.__name__
__str__
and/orを定義します。__repr__
次の例は、これらのアプローチの両方を示しています。
#include <boost/python.hpp>
/// @brief Helper type used to set and get a boost::python::class_
/// object's type name.
template <typename ClassT>
class typed_class_name
{
public:
/// @brief Extract and store the __name__ from a
/// boost::python::class_ objct.
static void set(const ClassT& c)
{
name_ = boost::python::extract<std::string>(c.attr("__name__"));
}
/// @brief Return the stored name.
static std::string get(const typename ClassT::wrapped_type&)
{
std::cout << "typed" << std::endl;
return name_;
}
private:
static std::string name_;
};
template <typename ClassT> std::string typed_class_name<ClassT>::name_;
/// @brief Generically get a python object's class name.
struct generic_class_name
{
static boost::python::object get(const boost::python::object& self)
{
std::cout << "generic" << std::endl;
return self.attr("__class__").attr("__name__");
}
};
class my_def_visitor
: public boost::python::def_visitor<my_def_visitor>
{
friend class boost::python::def_visitor_access;
template <class ClassT>
void visit(ClassT& c) const
{
// Store the class name.
typed_class_name<ClassT>::set(c);
c
.def("__str__", &typed_class_name<ClassT>::get) // typed
.def("__repr__", &generic_class_name::get) // generic
;
}
};
class X {};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<X>("X")
.def(my_def_visitor())
;
}
そして使用法:
>>> import example
>>> x = example.X()
>>> str(x)
typed
'X'
>>> repr(x)
generic
'X'