boost/python/slice.hpp

はじめに

Python の slice 型に対する TypeWrapper をエクスポートする。

クラス

slice クラス

class slice : public object

Python の組み込み slice 型をラップして拡張スライシングプロトコルをエクスポートする。インターフェイス以下に定義するコンストラクタとメンバ関数のセマンティクスを完全に理解するには、TypeWrapper コンセプトの定義を読むことである。sliceobject から公開派生しているので、object の公開インターフェイスは slice のインスタンスにも当てはまる。

slice クラスの概要

namespace boost { namespace python
{
  class slice : public object
  {
   public:
      slice(); // 空の slice を作成する。[::] と等価

      template <typename Int1, typename Int2>
      slice(Int1 start, Int2 stop);

      template <typename Int1, typename Int2, typename Int3>
      slice(Int1 start, Int2 stop, Int3 step);

      // この slice を作成したときの引数にアクセスする。
      object start();
      object stop();
      object step();

      // slice::get_indices() の戻り値の型
      template <typename RandomAccessIterator>
      struct range
      {
          RandomAccessIterator start;
          RandomAccessIterator stop;
          int step;
      };

      template <typename RandomAccessIterator>
      range<RandomAccessIterator>
      get_indices(
          RandomAccessIterator const& begin,
          RandomAccessIterator const& end);
  };
}}

slice クラスのコンストラクタ

slice()
効果

既定の stop 、start 、step 値で slice を構築する。Pythonの式 base[::] で作成したスライスオブジェクトと等価。

例外

なし。

template<typename Int1, typename Int2>
slice(Int1 start, Int2 stop)

start および stopslice_nil 型、または object 型へ変換可能。

効果

既定の step 値と与えられた startstop 値で新しい slice を構築する。Python の組み込み関数 slice(start, stop) 、または Python の式 base[start:stop] で作成したスライスオブジェクトと等価。

例外

error_already_set -- 引数を object 型へ変換できない場合(Python の TypeError 例外を設定する)。

template<typename Int1, typename Int2, typename Int3>
slice(Int1 start, Int2 stop, Int3 step)
要件

startstop および stepslice_nil 、または object 型へ変換可能。

効果

startstopstep 値で新しい slice を構築する。Python の組み込み関数 slice(start, stop, step) 、または Python の式 base[start:stop:step] で作成したスライスオブジェクトと等価。

例外

error_already_set -- 引数を object 型へ変換できない場合(Python の TypeError 例外を設定する)。

slice クラスのオブザーバ関数

object start() const
object stop() const
object step() const
効果

なし。

例外

なし。

戻り値

スライスを作成したときに使用した引数。スライスを作成したときに引数を省略したか slice_nil を使用した場合、その引数は Py_None への参照でありデフォルトコンストラクトされた object と等値である。原則的にはスライスオブジェクトを作成するのに任意の型を使用できるが、現実的には大抵は整数である。

template<typename RandomAccessIterator>
range<RandomAccessIterator> get_indices(RandomAccessIterator const &begin, RandomAccessIterator const &end) const
Param

半開区間を形成する STL 準拠のランダムアクセスイテレータの組。

効果

引数の [begin,end) 範囲内の完全閉範囲を定義する RandomAccessIterator の組を作成する。Py_None か負の添字の効果、および 1 以外の step サイズをどう扱うか説明を求められたときに、この関数がスライスの添字を変換する。

戻り値

非 0 の step 値と、この関数の引数が与える範囲を指し閉区間を定義する RandomAccessIterator の組で初期化した slice::range

例外
  • error_already_set -- このスライスの引数が Py_None への参照でも int へ変換可能でもない場合。Python の TypeError 例外を:term:送出する

  • std::invalid_argument -- 結果の範囲が空の場合。slice::get_indices を呼び出すときは常に try { ...; } catch (std::invalid_argument) {} で囲んでこのケースを処理し適切に処置しなければならない。

根拠

閉区間。開空間を使ったとすると、step サイズが 1 以外の場合、終端のイテレータが末尾の直後より後方の位置や指定した範囲より前方を指す状態が必要となる。

空のスライスに対する例外。空の範囲を表す閉区間を定義することは不可能であるので、未定義の動作を防止するために他の形式のエラーチェックが必要となる。例外が捕捉されない場合、単に既定の例外処理機構により Python に変換される。

using namespace boost::python;

// Python リストの拡張スライス。
// 警告:組み込み型に対する拡張スライシングは Python 2.3 より前ではサポートされていない
list odd_elements(list l)
{
    return l[slice(_,_,2)];
}

// std::vector のスライスに対して合計をとる。
double partial_sum(std::vector<double> const& Foo, const slice index)
{
    slice::range<std::vector<double>::const_iterator> bounds;
    try {
        bounds = index.get_indices<>(Foo.begin(), Foo.end());
    }
    catch (std::invalid_argument) {
        return 0.0;
    }
    double sum = 0.0;
    while (bounds.start != bounds.stop) {
        sum += *bounds.start;
        std::advance( bounds.start, bounds.step);
    }
    sum += *bounds.start;
    return sum;
}