閉じる

【Python】リストの一部を取り出す方法:スライスの書き方とコツ

Pythonのリストから一部だけを取り出すには「スライス」が便利です。

範囲だけでなく、間隔や逆順も柔軟に指定できます。

この記事では基本構文からよく使う例、つまずきやすい注意点まで、初心者向けに順を追って丁寧に解説します。

リストのスライスとは

スライスとは、リストから一部分を切り出して新しいリストを作る機能のことです。

英語の「slice(薄切り)」のイメージ通り、元のリストを傷つけずに、必要な範囲だけを取り出せます。

位置(インデックス)の開始、終了、取り出す間隔をまとめて指定でき、データ前処理や抽出、並び替えの準備などに広く使われます。

スライスの基本構文と書き方

start stop stepの指定

スライスの基本形は、list[start:stop:step]です。

startは開始位置、stopは終了位置(ただしstopの位置は含みません)、stepは何個おきに取り出すかの間隔です。

たとえば2つおきに取り出したい、というような指定ができます。

stepは省略可能ですが、0は指定できません。

0を指定するとエラーになります。

Python
# 基本のサンプル
nums = [10, 20, 30, 40, 50, 60, 70]

# start=1, stop=5, step=2 → インデックス1(20)から1つ飛ばしでstop直前(インデックス4まで)
part1 = nums[1:5:2]  # [20, 40]

# start=0, stop=3(=インデックス0〜2) → 最初の3つ
part2 = nums[0:3]    # [10, 20, 30]

# stepに0は指定不可 → 例外(ValueError)になるので捕捉して表示
try:
    bad = nums[::0]
except ValueError as e:
    print("エラー:", e)

print("part1:", part1)
print("part2:", part2)
実行結果
エラー: slice step cannot be zero
part1: [20, 40]
part2: [10, 20, 30]

stopは含まない

スライスのstopは「含まない(排他的)」のが重要なポイントです。

開始位置は含む一方、終了位置は含まれません。

したがって、意図した数に満たない結果になっていないか、最初は出力を確認しながら慣れると安心です。

Python
nums = [10, 20, 30, 40, 50, 60]

# インデックスと値の対応を確認しやすいように表示
print("インデックスと値:", list(enumerate(nums)))

# インデックス1から3まで(3は含まないので実際は1,2が対象)
print("nums[1:3] →", nums[1:3])  # [20, 30]

# インデックス1から4まで(4は含まないので1,2,3が対象)
print("nums[1:4] →", nums[1:4])  # [20, 30, 40]
実行結果
インデックスと値: [(0, 10), (1, 20), (2, 30), (3, 40), (4, 50), (5, 60)]
nums[1:3] → [20, 30]
nums[1:4] → [20, 30, 40]

省略時の動き

startstopstepは省略できます。

省略したときのデフォルトは以下の通りです。

省略項目デフォルト値意味
start0先頭から開始
stoplen(list)末尾の次(末尾まで)
step11つずつ取り出す
Python
nums = [10, 20, 30, 40, 50, 60]

# 先頭からインデックス3の直前まで
print("nums[:3]   →", nums[:3])    # [10, 20, 30]

# インデックス3から末尾まで
print("nums[3:]   →", nums[3:])    # [40, 50, 60]

# 2つおきに取り出す
print("nums[::2]  →", nums[::2])   # [10, 30, 50]

# すべて(完全コピーと同じ結果。ただしこの書き方の解説は後述)
print("nums[:]    →", nums[:])     # [10, 20, 30, 40, 50, 60]
実行結果
nums[:3]   → [10, 20, 30]
nums[3:]   → [40, 50, 60]
nums[::2]  → [10, 30, 50]
nums[:]    → [10, 20, 30, 40, 50, 60]

スライスとインデックスの違い

インデックス(list[i])は単一要素を取り出し、スライス(list[i:j])はリストを返します。

この違いは型やエラーの出方にも影響します。

Python
nums = [10, 20, 30, 40, 50]

# 単一要素の取り出し(型はint)
one = nums[2]
print("nums[2]:", one, "型:", type(one))

# 1要素でもスライスはリスト(型はlist)
sub = nums[2:3]
print("nums[2:3]:", sub, "型:", type(sub))

# インデックスは範囲外だと例外(IndexError)
try:
    _ = nums[100]
except IndexError as e:
    print("インデックスの範囲外:", e)

# スライスは範囲外でも空リストが返る
print("nums[100:101]:", nums[100:101])
実行結果
nums[2]: 30 型: <class 'int'>
nums[2:3]: [30] 型: <class 'list'>
インデックスの範囲外: list index out of range
nums[100:101]: []

よく使うスライス例

先頭から指定位置まで

先頭からn個分を取り出すときは [:n] を使います。

nは「含まない位置」なので、n=3ならインデックス0〜2が対象です。

Python
letters = ["a", "b", "c", "d", "e", "f"]
head3 = letters[:3]
print(head3)  # ["a", "b", "c"]
実行結果
['a', 'b', 'c']

指定位置から末尾まで

ある位置以降をすべて取り出すには [n:] を使います。

nは開始位置(含む)です。

Python
letters = ["a", "b", "c", "d", "e", "f"]
tail_from_3 = letters[3:]  # インデックス3(= "d")から末尾まで
print(tail_from_3)
実行結果
['d', 'e', 'f']

指定範囲の部分リスト

i以上、j未満の範囲を取り出すには [i:j] を使います。

範囲の両端を明確に決めたいときに便利です。

Python
letters = ["a", "b", "c", "d", "e", "f"]
mid = letters[2:5]  # インデックス2〜4 ("c","d","e")
print(mid)
実行結果
['c', 'd', 'e']

逆順のリスト

全体を逆順にしたいときは [::-1] が最短です。

部分的に逆方向へ進めたいときは開始と終了を逆転させ、stepに-1を指定します。

Python
letters = ["a", "b", "c", "d", "e", "f"]

all_rev = letters[::-1]       # 全体の逆順
part_rev = letters[4:1:-1]    # インデックス4から2まで逆方向("e","d","c")

print("全体逆順:", all_rev)
print("部分逆順:", part_rev)
実行結果
全体逆順: ['f', 'e', 'd', 'c', 'b', 'a']
部分逆順: ['e', 'd', 'c']

一定間隔で取り出す

等間隔で要素を抽出するには step を使います。

偶数番目(0始まり)や奇数番目だけを取り出す用途にもよく使います。

Python
letters = ["a", "b", "c", "d", "e", "f", "g"]

even_indexed = letters[::2]  # 0,2,4,6番目
odd_indexed  = letters[1::2] # 1,3,5番目
every_three  = letters[::3]  # 3つおき

print("2つおき:", even_indexed)
print("1つずらしで2つおき:", odd_indexed)
print("3つおき:", every_three)
実行結果
2つおき: ['a', 'c', 'e', 'g']
1つずらしで2つおき: ['b', 'd', 'f']
3つおき: ['a', 'd', 'g']

スライスのコツと注意点

負のインデックスと負のステップ

負のインデックスは「末尾からの数え方」を表します。

-1は最後、-2は最後から2番目を意味します。

また、stepを負にすると右から左へ進みます。

Python
s = ["a", "b", "c", "d", "e", "f"]

print("s[-1] (最後):", s[-1])          # 'f'
print("s[-3:-1] (最後から3〜1手前):", s[-3:-1])  # ['d', 'e']
print("s[::-1] (全体逆順):", s[::-1])   # ['f','e','d','c','b','a']

# 最後から3つ取り出す(逆方向で区間を指定)
print("s[-1:-4:-1]:", s[-1:-4:-1])     # ['f','e','d']
実行結果
s[-1] (最後): f
s[-3:-1] (最後から3〜1手前): ['d', 'e']
s[::-1] (全体逆順): ['f', 'e', 'd', 'c', 'b', 'a']
s[-1:-4:-1]: ['f', 'e', 'd']

範囲外でもエラーにならない

インデックスと違い、スライスは範囲外でも例外にならず、可能な部分を返すか空リストになります。

これにより安全に切り出しができます。

Python
s = ["a", "b", "c", "d", "e"]

# インデックスは範囲外で例外
try:
    _ = s[100]
except IndexError as e:
    print("インデックス範囲外:", e)

# スライスは範囲外でも安全
print("s[100:200]:", s[100:200])  # 空リスト
print("s[-100:3]:", s[-100:3])    # 先頭〜インデックス2
print("s[3:100]:", s[3:100])      # インデックス3〜末尾まで
実行結果
インデックス範囲外: list index out of range
s[100:200]: []
s[-100:3]: ['a', 'b', 'c']
s[3:100]: ['d', 'e']

スライスが返すコピー

スライスは新しいリスト(コピー)を返します。

したがって、取り出した側を変更しても元のリストは変わりません。

ただし「浅いコピー(シャローコピー)」なので、ネストしたリストの中身は共有される点に注意が必要です。

Python
# 単純なリストでは独立している
a = [1, 2, 3, 4]
b = a[1:3]         # [2,3] の新しいリスト
b[0] = 999
print("a:", a)     # 変更されない
print("b:", b)

# ネストしたリストでは中身(内側のリスト)は共有される
nested = [[1, 2], [3, 4]]
shallow = nested[:]     # 浅いコピー
shallow[0][0] = 99      # 内側の要素を書き換える
print("nested:", nested)  # 影響を受ける
print("shallow:", shallow)
実行結果
a: [1, 2, 3, 4]
b: [999, 3]
nested: [[99, 2], [3, 4]]
shallow: [[99, 2], [3, 4]]

内側のオブジェクトも独立させたい場合は、copy.deepcopyを検討します。

Python
import copy

nested = [[1, 2], [3, 4]]
deep = copy.deepcopy(nested)  # 深いコピー
deep[0][0] = 99
print("nested:", nested)  # 影響なし
print("deep:", deep)
実行結果
nested: [[1, 2], [3, 4]]
deep: [[99, 2], [3, 4]]

リスト全体をコピーする

リスト全体のコピーにはいくつか方法があります。

[:]、list()、copy()はいずれも新しいリストを作る点は共通ですが、代入(=)は単なる参照の共有になります。

方法新しいリストか備考
a[:]はいスライスで全体コピー(浅いコピー)
list(a)はいコンストラクタでコピー(浅いコピー)
a.copy()はいメソッドでコピー(浅いコピー)
b = aいいえ参照を共有(同じオブジェクト)
Python
a = [1, 2, 3]
b = a[:]       # スライス
c = list(a)    # コンストラクタ
d = a.copy()   # メソッド
e = a          # 参照の共有(エイリアス)

print("a is b:", a is b)
print("a is c:", a is c)
print("a is d:", a is d)
print("a is e:", a is e)  # これだけTrue

# 参照共有の違いを確認
e[0] = 999
print("a:", a)  # aも変わる
print("e:", e)
print("b:", b)  # b, c, dは変わらない
print("c:", c)
print("d:", d)
実行結果
a is b: False
a is c: False
a is d: False
a is e: True
a: [999, 2, 3]
e: [999, 2, 3]
b: [1, 2, 3]
c: [1, 2, 3]
d: [1, 2, 3]

まとめ

スライスは、list[start:stop:step]という簡潔な書き方で、範囲指定、逆順、間隔抽出などを柔軟にこなせる強力な機能です。

特に「stopは含まない」「省略時のデフォルト(start=0stop=len(list)step=1)」「範囲外でもエラーにならない」という3点を押さえると、思い通りに操作しやすくなります。

また、スライスは新しいリストを返すため安全に加工できますが、浅いコピーであることや、stepに0は指定できないことには注意してください。

基本とコツを身につければ、データの前処理や部分抽出が格段に書きやすくなります。

Python データ構造 (リスト・辞書など)
この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!