Pythonエンジニア認定基礎試験の勉強をしていたところ、
リストのスライスについて躓いたのでメモとして残します。
スライスとは
下記の通り、開始・終了・ステップを指定することで、リスト(厳密にはシーケンス型)の一部を切り取ることができる記法。
list[start:stop:step]
公式ドキュメントでの説明
公式ドキュメントでは下記の通り。
a[i:j:k] は、 x = i + n*k, n >= 0 かつ i <= x < j であるようなインデクス x を持つような a 全ての要素を選択します。
よくある説明
Pythonチュートリアルをはじめ、初学者向けには下記のように説明されることが多い。
下記の通り、各要素の区切り線に番号をふり、
startとstopで指定された区間に含むものを切り取るという考え方です。
スライスの使い方をおぼえる良い方法は、インデックスが文字と文字の あいだ (between) を指しており、最初の文字の左端が 0 になっていると考えることです。そうすると、 n 文字からなる文字列中の最後の文字の右端はインデックス n となります。例えばこうです:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
よくある説明の問題点
一見、この説明でほとんどのケースでは問題ありませんが、
stepが負となるケースについては下記の通り、
説明することができません。
list = ['P','y','t','h','o','n']
print(list[5:1:-1]) #['n', 'o', 'h', 't']
たどり着いた理解の仕方
そこで、自分であればどう説明するかと考えたのが下記の理解。
各パラメータの意味
start: 開始位置のインデックス(この点を含む)
end:終了位置のインデックス(この点は含まない)
step:何個横にずらして値を取得するか(初期値1)
要点としては、下記の通り、区切り線ではなくインデックスで理解をする
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
スライス操作のイメージ
- startとendを比較し、区間に値が含まれるか判定する
- stepが正の場合は
start < end
、負の場合はend < start
であればOK - 条件を満たさない場合は、空(
[]
)を返す
- stepが正の場合は
- startの値と、startの値にstepを足し続け、「end以上」となる一つ手前まで値を取得する
例:
サンプル1(stepが正の場合)
list = ['P','y','t','h','o','n']
print(list[1:5:2])
-
step > 0
かつstart < end
なのでOK -
list[1]
のy
を取得 - [1]にstepの2を足すと[3]となる。[3]はend未満なので、
list[3]
のh
を取得 - [3]にstepを足すと、[5]となるが、[5]はendと等しくなるので取得しない
よって['y','h']
サンプル2(stepが負の場合)
list = ['P','y','t','h','o','n']
print(list[5:1:-1])
-
step < 0
かつstart > end
なのでOK -
list[5]
のn
を取得 - [5]にstepの-1を足すと[4]となる。[4]はend未満なので、
list[4]
のo
を取得 - [4]にstepの-1を足すと[3]となる。[3]はend未満なので、
list[3]
のh
を取得 - [3]にstepの-1を足すと[2]となる。[2]はend未満なので、
list[2]
のt
を取得 - [2]にstepを足すと、[1]となるが、[1]はendと等しくなるので取得しない
よって['n','o','h','t']
サンプル3(startとendの関係性が逆の場合)
list = ['P','y','t','h','o','n']
print(list[5:1:3])
-
step > 0
だがstart < end
ではない。したがって、空
よって[]
おまけ(ChatGPTによる説明)
基本構文:
start: スライスを開始するインデックス(最初の要素は0)。省略するとリストの最初から始まります。
end: スライスを終了するインデックス。このインデックスの要素は含まれません。省略するとリストの最後まで取得されます。
step: 要素を何個飛ばしで取得するかを指定します。省略すると1(順番に取得)になります。
案外わかりやすい気もします。。。。