リストの一部を抜き出す方法は、Pythonではスライスと呼ばれます。
スライスを使うと、範囲指定で安全かつ簡潔に部分列を取り出せるため、要素の抽出、並べ替え、コピーなど多くの場面で役立ちます。
本記事では、基本の記法、よく使う省略、実践テク、注意点を、丁寧なサンプルコードと出力つきで解説します。
Pythonのリストのスライスとは?
スライスの基本(部分取り出し)
スライスは、リストの一部を新しいリストとして取得する仕組みです。
元のリストを壊さずに、必要な範囲だけを抽出できます。
# 基本となるリスト
nums = [10, 20, 30, 40, 50, 60]
# 2番目から4番目までを取り出す例(インデックスは0始まり)
part = nums[1:4] # 20, 30, 40 が取り出される
print(part)
print(nums) # 元のリストは変化しません
[20, 30, 40]
[10, 20, 30, 40, 50, 60]
構文 list[start:end] の書き方
スライスの基本構文はlist[start:end]
です。
start以上、end未満の要素が対象になります。
例えばa[2:5]
は、インデックス2, 3, 4を取得します。
a = ['a', 'b', 'c', 'd', 'e', 'f']
print(a[2:5]) # c, d, e を取得
['c', 'd', 'e']
インデックスは0始まり
Pythonのインデックスは0から始まります。
先頭は0
、2番目は1
です。
letters = ['A', 'B', 'C', 'D']
print(letters[0], letters[1]) # 先頭と2番目を確認
print(letters[0:2]) # 0以上2未満 → A, B
A B
['A', 'B']
endは含まない(半開区間)
右端のendは含まれません(半開区間)。
これにより、連続した範囲を重ねても重複が起きず、境界の計算が簡単になります。
x = [0, 1, 2, 3, 4]
print(x[1:3]) # 1, 2 を取得。3は含まれない
print(x[:3]) # 0, 1, 2
print(x[3:]) # 3, 4
[1, 2]
[0, 1, 2]
[3, 4]
範囲外アクセス時の挙動(例外にならない)
スライスは、範囲外でも例外にならず、存在する範囲だけを返します。
一方、添字アクセスa[index]
は範囲外でIndexErrorになります。
a = [1, 2, 3]
# スライスは静かに空リストを返す
print(a[10:20]) # []
# 添字アクセスは例外
try:
print(a[10])
except IndexError as e:
print("IndexError:", e)
[]
IndexError: list index out of range
- 関連記事:例外(Exception)入門
スライスの書き方と省略記法
先頭から/末尾までの省略 [:end] [start:]
start
やend
は省略できます。
省略された側は、それぞれ先頭または末尾が補われます。
a = [10, 20, 30, 40, 50]
print(a[:3]) # 先頭から3要素: [10, 20, 30]
print(a[2:]) # 2番目以降すべて: [30, 40, 50]
[10, 20, 30]
[30, 40, 50]
全体コピー list[:]
list[:]
は全体の浅いコピーを作ります。
元のリストとは別オブジェクトになります。
a = [1, 2, 3]
b = a[:] # 全体コピー
b.append(99)
print("a:", a)
print("b:", b)
print("同一オブジェクトか:", a is b)
a: [1, 2, 3]
b: [1, 2, 3, 99]
同一オブジェクトか: False
負のインデックスで末尾基準 [-n:]
負のインデックスは末尾からの相対位置を表します。
例えば-1
は末尾、-2
は末尾の1つ前です。
a = [10, 20, 30, 40, 50]
print(a[-2:]) # 末尾2件: [40, 50]
print(a[:-2]) # 末尾2件を除く: [10, 20, 30]
[40, 50]
[10, 20, 30]
- 関連記事:リストを逆順ソート/反転する3つの方法
ステップ指定 list[start:end:step]
3番目のパラメータstep
で、間引きや逆方向を指定できます。
正の値なら前方向、負の値なら逆方向に進みます。
a = [0, 1, 2, 3, 4, 5, 6]
print(a[1:6:2]) # 1から5まで2刻み: [1, 3, 5]
print(a[5:1:-2]) # 5から2まで逆向き2刻み: [5, 3]
[1, 3, 5]
[5, 3]
2件おきの取り出し [::2]
[::2]
は配列全体から2件おきに取得します。
a = list(range(10)) # 0〜9
print(a[::2]) # 偶数番インデックスの要素
[0, 2, 4, 6, 8]
逆順の取り出し [::-1]
[::-1]
は簡単な反転です。
a = [1, 2, 3, 4]
print(a[::-1]) # 逆順コピー
[4, 3, 2, 1]
stepに0は不可
stepに0は指定できません。
ValueErrorになります。
a = [1, 2, 3]
try:
print(a[::0])
except ValueError as e:
print("ValueError:", e)
ValueError: slice step cannot be zero
実践テクニックと注意点
スライスは新しいリストを返す(コピー)
スライスの結果は元とは別のリストです。
結果を変更しても元には影響しません。
a = [10, 20, 30, 40]
b = a[1:3] # [20, 30]
b[0] = 999 # bのみ変更
print("a:", a)
print("b:", b)
a: [10, 20, 30, 40]
b: [999, 30]
スライス代入で部分更新・挿入・削除
スライスは「取得」だけでなく代入で更新や挿入、削除にも使えます。
a = [10, 20, 30, 40, 50]
# 部分更新: 2番目から3要素を置き換え
a[1:4] = [200, 300] # 要素数が違ってもOK(短くなる)
print("更新:", a) # [10, 200, 300, 50]
# 挿入: 幅0スライスに代入すると差し込みになる
a[2:2] = [777, 888]
print("挿入:", a) # [10, 200, 777, 888, 300, 50]
# 削除: 空リストを代入、またはdelと組み合わせ
a[1:4] = [] # 200, 777, 888を削除
print("削除(代入):", a)
del a[-2:] # 末尾2件を削除
print("削除(del):", a)
更新: [10, 200, 300, 50]
挿入: [10, 200, 777, 888, 300, 50]
削除(代入): [10, 300, 50]
削除(del): [10]
- 関連記事:リストの追加・変更削除
浅いコピーの注意(ネストしたリスト)
スライスは浅いコピーです。
入れ子(ネスト)の内側オブジェクトは共有されます。
内側を書き換えると両方に影響します。
nested = [[1, 2], [3, 4]]
copy1 = nested[:] # 浅いコピー
copy1[0][0] = 999 # 内側のリストを変更
print("nested:", nested)
print("copy1 :", copy1)
nested: [[999, 2], [3, 4]]
copy1 : [[999, 2], [3, 4]]
深いコピーが必要ならcopy.deepcopy
を使います。
import copy
nested = [[1, 2], [3, 4]]
deep = copy.deepcopy(nested)
deep[0][0] = 999
print("nested:", nested)
print("deep :", deep)
nested: [[1, 2], [3, 4]]
deep : [[999, 2], [3, 4]]
添字アクセスとの違い(安全性と戻り値)
添字アクセスとスライスの主な違いは次の通りです。
使い方 | 戻り値の型 | 範囲外の挙動 | 例 |
---|---|---|---|
a[i] | 要素(単一) | IndexError | [1,2,3][10] は例外 |
a[i:j] | リスト | 空リストを返す | [1,2,3][10:20] は[] |
これにより、境界が不確かな場面ではスライスの方が安全に扱えます。
境界指定のコツ(lenと組み合わせる)
len(a)
と組み合わせると、データ長が変わっても壊れにくいコードになります。
a = [0, 1, 2, 3, 4, 5]
n = 3
print(a[:n]) # 先頭n件
print(a[-n:]) # 末尾n件
mid = len(a) // 2
window = 4
print(a[mid:mid+window]) # 中央から幅4件(足りなければ末尾まで)
[0, 1, 2]
[3, 4, 5]
[3, 4, 5]
多次元リストのスライスの考え方
リストのリスト(2次元)でも、スライスは各次元ごとに適用します。
列方向の抽出は内側のリストに対してスライスする必要があります。
m = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
# 行スライス: 先頭2行
print(m[:2])
# 列スライス: 各行の1〜2列目を抽出(内側にスライス)
cols_1_2 = [row[0:2] for row in m]
print(cols_1_2)
# 行の逆順、隔行の取得
print(m[::-1]) # 行の逆順
print(m[::2]) # 0行目、2行目
[[1, 2, 3], [4, 5, 6]]
[[1, 2], [4, 5], [7, 8]]
[[7, 8, 9], [4, 5, 6], [1, 2, 3]]
[[1, 2, 3], [7, 8, 9]]
- 関連記事:リスト内包表記でfor文を置き換える
よくある使い方と練習パターン
先頭n件・末尾n件を取り出す
よく使う抽出は、[:n]
と[-n:]
です。
不足しても例外にならず、存在する範囲だけが返ります。
scores = [68, 72, 81, 90, 77]
n = 3
print("先頭n件:", scores[:n])
print("末尾n件:", scores[-n:])
先頭n件: [68, 72, 81]
末尾n件: [81, 90, 77]
中央の部分列を切り出す
配列中央から幅w
のウィンドウを取り出す例です。
偶数・奇数長どちらにも対応します。
data = list(range(1, 11)) # 1〜10
w = 4
start = (len(data) - w) // 2 # 中央に揃える開始位置
print(data[start:start+w])
[4, 5, 6, 7]
条件に合う範囲を抽出する(インデックス計算)
値の範囲など条件で区間を抜き出すには、開始と終了のインデックスを求めてからスライスします。
times = [5, 8, 12, 15, 18, 20, 25]
# 10以上18以下の区間を抽出
lo, hi = 10, 18
# 開始位置: 最初にlo以上になるインデックス
start = next((i for i, v in enumerate(times) if v >= lo), len(times))
# 終了位置: 最初にhiを超えるインデックス(スライスのendは含まない)
end = next((i for i, v in enumerate(times) if v > hi), len(times))
print("抽出:", times[start:end])
抽出: [12, 15, 18]
部分置換・一括削除(del + slice)
範囲の置換や削除は、スライス代入やdel
と組み合わせると一発です。
a = list("abcdefg")
# 文字列の一部置換(リストで扱う)
a[2:5] = list("XYZ") # 'cde' → 'XYZ'
print("置換:", "".join(a))
# 一括削除: 先頭3件を削除
del a[:3]
print("削除:", "".join(a))
置換: abXYZfg
削除: YZfg
逆順スライスでの処理([::-1])
[::-1]
で逆順に走査すると、後方から安全に処理できる場面があります。
ここでは逆順で出力しつつ、元リストは保持する例です。
words = ["alpha", "beta", "gamma", "delta"]
# 逆順に処理(元は不変)
for w in words[::-1]:
print(w.upper())
print("元:", words)
DELTA
GAMMA
BETA
ALPHA
元: ['alpha', 'beta', 'gamma', 'delta']
なお、要素の削除を伴う場合は、元リストを直接走査しながらremoveするのは危険です。
削除はdel a[i:j]
や条件で新リストを作る方法を検討してください。
- 関連記事:リストを逆順ソート/反転する3つの方法
まとめ
スライスは安全で柔軟な部分取り出しを実現するPythonの重要機能です。
半開区間(右端は含まない)、省略記法、負のインデックス、ステップを理解すれば、抽出、反転、間引き、コピーまで幅広く対応できます。
さらに、スライス代入で更新・挿入・削除も直感的に行えます。
浅いコピーの性質や多次元リストでの取り扱いに注意しつつ、lenと組み合わせた境界指定や[::-1]
などの定番パターンを手に馴染ませてください。
スライスを使いこなすことで、リスト操作の可読性と堅牢性が大きく向上します。
- 関連記事:リストの長さを取得する – len()