スライスで部分リストを取り出す

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

このレッスンで分かること

  • list[start:stop:step] の 1 行で部分リストを取り出せます
  • stop は含まれません (半開区間 [start, stop))
  • 最小例は numbers[:3] で先頭 3 件、numbers[::-1] で反転

スライスで部分リストを取り出す とは

Python のスライス記法でリストの部分を切り出す方法を学びます。本レッスンでは、スライスで部分リストを取り出す の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

スライスで部分リストを取り出す

リストから「先頭 3 件だけ」「後ろから 2 件」「2 つおき」など、部分 を取り出したい場面は多いはず。Python はこれを スライス という記法でまとめて解決してくれます。for ループや if で 1 件ずつ取り出さなくても、たった一行で必要な範囲を切り抜ける、それがスライスの強みです。データ分析や前処理、Web API のレスポンス整形など、シーケンスを扱うあらゆる場面で スライス は活躍します。

スライスは list[start:stop:step] の形で書きます。start を省略すれば先頭から、stop を省略すれば末尾まで、step を省略すれば 1 つずつ進みます。

スライスとは何か

スライスは リスト タプル 文字列 などのシーケンス型に共通する記法です。[] の中に start stop stepコロン で区切って渡すだけで、対応する範囲を新しいリストとして返してくれます。元のリストを破壊しないので、安心して何度でも切り出せます。これは関数型プログラミングでよく言う「イミュータブル な操作」と相性が良く、副作用を最小化したコードを書きやすくしてくれます。

Python

numbers = [10, 20, 30, 40, 50] print(numbers[1:4]) # [20, 30, 40] print(numbers[:3]) # [10, 20, 30] print(numbers[2:]) # [30, 40, 50] print(numbers[::2]) # [10, 30, 50] print(numbers[::-1]) # [50, 40, 30, 20, 10]

注目すべきは stop の挙動です。numbers[1:4] は index 1 から 3 までで、4含まれません。「stop は含まない」、これが Python のスライスの基本ルールです。range(1, 4)1, 2, 3 を生成するのと同じく、Python の世界では半開区間 [start, stop) がデフォルトになっています。

文法のおさらい

step を負の値にすると逆方向に走査でき、結果としてリストを反転させることもできます。下の表は numbers = [10, 20, 30, 40, 50] での代表的な例です。

書き方結果意味
numbers[0:2][10, 20]先頭から 2 件
numbers[-2:][40, 50]末尾 2 件
numbers[::-1][50, 40, 30, 20, 10]反転
numbers[1::2][20, 40]奇数 index だけ
numbers[:-1][10, 20, 30, 40]末尾 1 件を除く

負の index -1 は末尾の要素を指します。numbers[-2:] で「末尾 2 件」が取れるのは、start=-2 stop=省略 と書いているからです。

動きを追ってみる

diagram (will load when visible)

図の流れを順序リストで書き直すと、次の通りです。

  1. 元のリストを参照する
  2. start 位置を決める (省略時は 0)
  3. stop 位置を決める (省略時は末尾)
  4. step 幅で要素を集める (省略時は 1)
  5. 新しいリストとして返す (元のリストは変更されない)

スライスは「元のリストを変更せず、新しいリストを返す」という性質を覚えておきましょう。numbers[:3] の戻り値を変数に代入すれば、元の numbers は無傷のまま部分リストだけが新しく作られます。これを シャローコピー と呼びます。numbers[:] と書けばリスト全体の浅いコピーが手に入るので、コピー目的でもスライスは便利です。

Python

first_three = numbers[:3] first_three.append(999) print(first_three) # [10, 20, 30, 999] print(numbers) # [10, 20, 30, 40, 50] ← 元データは変わらない

スライスは文字列にも使えます。text = "PYTHON" のとき text[1:4]"YTH"text[::-1]"NOHTYP" です。リストと文字列で同じ感覚が通じる、これも Python の気持ちよさの一つです。

よくある間違い

  1. stop を「含まれる」と勘違いしてしまう。numbers[0:3] は index 3 を含まないので 3 件だけ取れる、と覚えましょう
  2. 負の step のとき startstop の指定順序を逆にしてしまう。numbers[4:0:-1] のように 大きい index から小さい index へ 書くのが正解です
  3. スライスで返るのは元と同じ型の新しいシーケンス。list をスライスすれば listtuple をスライスすれば tuple です。型が変わらないことに注意しましょう

スライスの範囲が空 (例えば numbers[5:2] のように start >= stop) の場合は、エラーにならず空のリスト [] が返ります。IndexError を心配せず気軽に書ける、これがスライスの懐の深さです。

この章のポイント

ここまでの要点 [start:stop:step]stop は含まない、省略すると「先頭から」「末尾まで」「1 つずつ」。元のリストは破壊されず新しいリストが返る。

やってみよう

引数 lst (リスト) を受け取り、先頭 3 件 を返す関数 slice_head_three を書いてみましょう。要素数が 3 未満なら、入っているだけ返せば OK です。スライスの stop の挙動を実感する練習にぴったりの一問です。一行で書けることに気付けば、スライスの便利さが体に染み込みます。

よくある質問

Q. スライスの終端はなぜ含まれないのですか?

A. 終端 end が「次の位置」を指す半開区間にすることで、a[:k] + a[k:] が元の配列に等しくなり、長さも end - start で計算できる利点があります。len(a[2:5]) は常に 3 で、off-by-one を起こしにくい設計になっています。

Q. 負のインデックスはどう動きますか?

A. 末尾からの位置を表します。a[-1] は最後の要素、a[-3:] は末尾 3 件、a[:-1] は最後を除く全要素です。逆順にしたいときは a[::-1] と書けば手軽に反転でき、文字列でも同じく動きます('abc'[::-1] → 'cba')。

Q. スライスはコピーですか参照ですか?

A. Python のリストスライスは浅いコピーを返します。a[:] と書けばリスト全体のコピーになります。ネストしたリストの場合、内側のリストは元と同じ参照を保持するため、深いコピーが必要なら copy.deepcopy を使ってください。

次のレッスン

次は リスト内包表記でループを 1 行に で、Python のスライス記法でリストの部分を切り出す方法を学びます を学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. スライス の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. スライス とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

要件

  1. スライス記法 lst[:3] を使って先頭 3 件を返す
  2. 元のリストを破壊しない
  3. 要素数が 3 未満でもエラーにならない

入出力例

test-cases.txt

slice_head_three([10,20,30,40,50])[10,20,30] slice_head_three(["a","b","c"])["a","b","c"] slice_head_three([1,2])[1,2] slice_head_three([])[]

ヒント

main.py
main.py
学習モード

メモ

スライスで部分リストを取り出す

⌘S で保存