Python'のslice記法について、良い説明(参考文献があれば尚可)が必要です。
私にとっては、この記法はちょっとした拾いものです。
非常に強力なものに見えますが、私はまだ理解できていません。
それはとてもシンプルなことです。
a[start:stop] # items start through stop-1
a[start:] # items start through the rest of the array
a[:stop] # items from the beginning through stop-1
a[:] # a copy of the whole array
また、step
という値もありますが、これは上記のいずれにも使用できます。
a[start:stop:step] # start through not past stop, by step
覚えておくべき重要なポイントは、:stop
値は、選択されたスライス内にない最初の値を表すということです。つまり、stop
とstart
の違いは、選択された要素の数です(step
がデフォルトの1の場合)。
もう1つの特徴は、start
や stop
には 負 の数を指定することができ、これは配列の最初ではなく最後から数えることを意味します。つまり
a[-1] # last item in the array
a[-2:] # last two items in the array
a[:-2] # everything except the last two items
同様に、step
には負の数を指定することができます。
a[::-1] # all items in the array, reversed
a[1::-1] # the first two items, reversed
a[:-3:-1] # the last two items, reversed
a[-3::-1] # everything except the last two items, reversed
Pythonは、要求した項目よりも少ない項目がある場合、プログラマに親切です。例えば、a[:-2]
を要求して、a
に1つの要素しか含まれていない場合、エラーではなく空のリストが得られます。エラーの方がいい場合もありますので、このようなことが起こる可能性があることを認識しておく必要があります。
slice()
オブジェクトとの関係スライス演算子 []
は、上のコードでは実際に slice()
オブジェクトと一緒に :
記法 (これは []
の中でのみ有効です) を使っています。
a[start:stop:step]
は次のようになります。
a[slice(start, stop, step)]
スライスオブジェクトは、range()
と同様に、引数の数に応じてわずかに異なる動作をします。つまり、slice(stop)
とslice(start, stop[, step])
の両方がサポートされています。
例えば、a[start:]
は a[slice(start, None)]
と同等であり、a[::-1]
は a[slice(None, None, -1)]
と同等であるように、与えられた引数の指定を省略するために、None
を使用することができます。
:ベースの表記法は単純なスライスには非常に便利ですが、
slice()`オブジェクトを明示的に使用することで、プログラムによるスライスの生成が簡単になります。
Pythonのチュートリアル]1には、このことが書かれています(スライスの部分まで少し下にスクロールしてください)。
ASCIIアートの図も、スライスの仕組みを覚えるのに役立ちます。
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
文法で許される可能性を列挙する。
>>> seq[:] # [seq[0], seq[1], ..., seq[-1] ]
>>> seq[low:] # [seq[low], seq[low+1], ..., seq[-1] ]
>>> seq[:high] # [seq[0], seq[1], ..., seq[high-1]]
>>> seq[low:high] # [seq[low], seq[low+1], ..., seq[high-1]]
>>> seq[::stride] # [seq[0], seq[stride], ..., seq[-1] ]
>>> seq[low::stride] # [seq[low], seq[low+stride], ..., seq[-1] ]
>>> seq[:high:stride] # [seq[0], seq[stride], ..., seq[high-1]]
>>> seq[low:high:stride] # [seq[low], seq[low+stride], ..., seq[high-1]]
もちろん、(high-low)%stride !=0
であれば、終点はhigh-1
よりも少し下になります。
もしstride
が負の値であれば、カウントダウンしているので、順序が少し変わります。
>>> seq[::-stride] # [seq[-1], seq[-1-stride], ..., seq[0] ]
>>> seq[high::-stride] # [seq[high], seq[high-stride], ..., seq[0] ]
>>> seq[:low:-stride] # [seq[-1], seq[-1-stride], ..., seq[low+1]]
>>> seq[high:low:-stride] # [seq[high], seq[high-stride], ..., seq[low+1]]
拡張されたスライス(カンマや楕円を使ったもの)は、ほとんどの場合、(NumPyのような)特殊なデータ構造でのみ使用され、基本的な配列はそれらをサポートしていません。
>>> class slicee:
... def __getitem__(self, item):
... return repr(item)
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'