Python PR

【Python】スライスを使ってリストなどのシーケンスの要素に部分的にアクセスする方法

記事内に商品プロモーションを含む場合があります

この記事では、Pythonのスライスの使い方を解説します。

リストなどのシーケンス型のオブジェクトを使っていると部分的な要素にアクセスしたい場面が多々あります。そんな時は、スライスを使うことで必要な要素のみにアクセスできます。

スライスは、リスト含むシーケンスオブジェクトの要素をインデックスを用いて部分的に選択することができます。選択した要素は、取得・変更・削除を行うことができます。

それでは、スライスの使い方を見ていきましょう!

スライスの基本

スライスを使うことでシーケンスの要素を部分的に選択できる。スライスは以下のようにシーケンスの後ろの角括弧([])内にstartstopstepをコロン()で区切って指定します。

シーケンス[start:stop:step]
ポイント
  • start、stop、stepには、インデックスを指定する
  • start、stop、stepは、全て省略可能
  • 範囲外のインデックスを指定してもエラーにならない
  • シーケンス: 複数の要素を順序付けして保存できるコレクションのこと(リスト、タプル、文字列など)

スライスはシーケンスの先頭や末尾の要素を削って処理したい時に使われることが多い。

l = ['必要ない', '必要', '必要', '必要ない']

for e in l[1:-1]:
    print(e)
    # 必要
    # 必要

それでは、スライスのstartstopstepの指定方法を見ていきます。

startからstopまで: [start:stop]

スライスのstartstopを指定することでstart <= N < stopの要素を取得できます。

シーケンス[start:stop]

2 <= N < 4の範囲の要素を取得してみます。

l = [1, 2, 3, 4, 5, 6, 7]
print(l[2:4])  # [3, 4]

start > stopだと値は取得できません。

l = [1, 2, 3, 4, 5, 6, 7]
print(l[4:2])  # []

先頭からstopまで: [:stop]

スライスのstopのみを指定することで0 <= N < stopの要素を取得できます。

シーケンス[:stop]  # コロンを忘れないように注意

これは以下のコードと等価です。

シーケンス[0:stop]

0 <= N < 4の要素を取得してみます。

l = [1, 2, 3, 4, 5, 6, 7]
print(l[:4])  # [1, 2, 3, 4]

コロンを忘れると通常のインデックス呼び出しになってしまうので注意。

l = [1, 2, 3, 4, 5, 6, 7]
print(l[4])  # 5

startから末尾まで: [start:]

スライスのstartのみ指定することでstartから末尾までの要素を取得できます。

シーケンス[start:]  # コロンを忘れないように注意

これは以下のコードと等価です。

シーケンス[start:len(シーケンス)]

2 <= N < len(vals)の範囲の要素を取得してみます。

l = [1, 2, 3, 4, 5, 6, 7]
print(l[2:])  # [3, 4, 5, 6, 7]

stepの指定: [::step]

スライスのstepを指定するとその数値ごとに要素が取得されます。stepを省略した場合はstep = 1となっています。

シーケンス[start:stop:step]

startstopを省略してステップ数のみを指定することもできます。

シーケンス[::step]  # コロンを忘れないように注意

異なるstepを指定して取得される要素がどのようになるか見てみましょう!

l = [1, 2, 3, 4, 5, 6, 7]

print(l[::2])  # [1, 3, 5, 7]
print(l[::3])  # [1, 4, 7]
print(l[::4])  # [1, 5]
print(l[::5])  # [1, 6]
print(l[::6])  # [1, 7]
print(l[::7])  # [1]

stepを指定することで任意の間隔で要素を取得することができます。アクセスしたい要素が一定間隔で配置されている場合に使用します。

全て省略: [:]、[::]

スライスのstartstopstepは省略可能です。なので以下のような書き方が可能です。

シーケンス[:]
シーケンス[::]

これらの書き方は全ての要素を取得します。

s = [1, 2, 3]

print(s[:])   # [1, 2, 3]
print(s[::])  # [1, 2, 3]

負の整数を指定する

スライスのstartstopstepに負の整数を指定することで末尾から要素を指定することができます。それぞれの挙動を見てみましょう。

l = [1, 2, 3, 4, 5, 6, 7]

# startに負の整数を指定する
print(l[-1:])    # [7]
print(l[-2:])    # [6, 7]
print(l[-3:])    # [5, 6, 7]
print(l[-4:])    # [4, 5, 6, 7]

# stopに負の整数を指定する
print(l[:-1])    # [1, 2, 3, 4, 5, 6]
print(l[:-2])    # [1, 2, 3, 4, 5]
print(l[:-3])    # [1, 2, 3, 4]
print(l[:-4])    # [1, 2, 3]

# startとstopに負の整数を指定する
print(l[-2:-1])  # [6]
print(l[-3:-1])  # [5, 6]
print(l[-4:-1])  # [4, 5, 6]

stepに負の整数を指定することで逆順で要素を取得できます。

l = [1, 2, 3, 4, 5, 6, 7]

print(l[::-1])  # [7, 6, 5, 4, 3, 2, 1]
print(l[::-2])  # [7, 5, 3, 1]
print(l[::-3])  # [7, 4, 1]

stepに負の整数を指定した場合にstartstopを指定するには以下のようになる。

l = [1, 2, 3, 4, 5, 6, 7]

print(l[-1:-8:-1])  # [7, 6, 5, 4, 3, 2, 1]
print(l[-1:-7:-1])  # [7, 6, 5, 4, 3, 2]
print(l[6::-1])     # [7, 6, 5, 4, 3, 2, 1] 
print(l[5:2:-1])    # [6, 5, 4]

これは直感的ではないので少し分かりづらいですね。あまりに手の込んだ指定方法は極力使わない方が良いかもしれませんね。

スライスオブジェクト

slice()でスライスオブジェクトを生成することができます。[]内にスライスオブジェクトを指定することで、その範囲で要素を選択できます。

slice(stop)
slice(start, stop[, step])

スライスオブジェクトを用いて範囲を指定して見ましょう!

l = [1, 2, 3, 4]

# スライスオブジェクト生成
so = slice(1, 3)
print(l[so])  # [2, 3]

スライスで選択した範囲の操作

スライスで選択した範囲は、取得するだけでなく代入や削除を行うことが可能です。

代入

スライスで選択した範囲にイテラブルオブジェクトを代入することができます。この時、選択した範囲と代入するイテラブルオブジェクトの要素数が異なっていても代入可能です。

l = [1, 2, 3, 4, 5]

l[1:4] = [10, 11]
print(l)  # [1, 10, 11, 5]

イテラブルオブジェクト以外のオブジェクト(スカラー値)を代入するとエラーが発生します。

l = [1, 2, 3, 4, 5]

l[1:4] = 10

実行結果

Traceback (most recent call last):
  File "/Users/user/Desktop/Python/main.py", line 3, in 
    l[1:4] = 10
    ~^^^^^
TypeError: can only assign an iterable

範囲外を指定することで新たに要素を挿入することもできます。

l = [1, 2, 3, 4, 5]

l[len(l):10] = [10, 11, 12]
print(l)  # [1, 2, 3, 4, 5, 10, 11, 12]

ただし、stepを指定した場合は、選択した範囲と代入するイテラブルオブジェクトの要素数が同じじゃないとエラーとなってしまうので注意してください。

l = [1, 2, 3, 4, 5]

l[1:4:2] = [10, 11]
print(l)  # [1, 10, 3, 11, 5]

l[1:4:3] = [10, 11]  # ValueError: attempt to assign sequence of size 2 to extended slice of size 1

削除

del文を使うことで選択した範囲の要素を削除することが可能です。

l = [1, 2, 3, 4, 5]

del l[1:4] 
print(l)  # [1, 5]

余談: スライスは浅いコピー

スライスで取得した値は浅いコピーで生成されたものである。つまりは、スライスで取得した値の中にネストされたリストや辞書があると元のオブジェクトに影響を及ぼしてしまう。

# ネストされたリストを含んだリスト
o = [[1, 2, 3], 4, 5]

# ネストされたリストを取得
s = o[:2]
print(s)  # [[1, 2, 3], 4]

# 変更を加える
s[0][0] = 10
print(s)  # [[10, 2, 3], 4]

# 元のオブジェクトも変わっている
print(o)  # [[10, 2, 3], 4, 5]

まとめ

この記事では、Pythonのスライスについて解説しました。

スライスを使うことでシーケンス型の要素に範囲的にアクセスすることができました。

実際にスライスを使用する場合、先頭、または末尾の要素以外を取得したいことが大体です。なので、以下のような方法さえ覚えておけば問題ありません。

l = ['必要ない', '必要', '必要', '必要ない']

print(l[1:-1])  # ['必要', '必要']

今回の内容はここまでです。それではまたどこかで〜( ・∀・)ノ