バックナンバー
- Python初心者が「Python文法詳解」を読んだメモ #1
- Python初心者が「Python文法詳解」を読んだメモ #2
- Python初心者が「Python文法詳解」を読んだメモ #3
- Python初心者が「Python文法詳解」を読んだメモ #4
第4章 シーケンスとコンテナ型
- Pythonでは、一般に配列と呼ばれる順序付きのコレクションをシーケンスと呼ぶ
- リスト型、タプル型、文字列型、バイト型など様々なデータ型があるが、いずれも同様に要素の操作ができる
添字によるアクセス
>>> L = [0, 1, 2, 3, 4, 5]
>>> L[2]
2
# インデックスとして負の値を指定すると、末尾から参照
>>> L[-1] # 最後尾の要素のインデックスは-1
5
>>> L[-2]
4
# 範囲外のインデックスを指定すると例外
>>> L[6]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
スライス
# インデックス値の範囲を指定して一括で取得
>>> L = [0, 1, 2, 3, 4]
>>> L[1:4]
[1, 2, 3] # 終了位置で指定した要素の一つ手前までの要素で新しいシーケンスオブジェクトを作成する
>>> L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> L[-5:-1] # 開始位置と終了位置が負の値の場合は、末尾からの位置指定となる
[5, 6, 7, 8]
>>> L[-5:0] # 末尾まで取りたい時は、こうではなくて
[]
>>> L[-5:] # こう
[5, 6, 7, 8, 9]
>>> L = [1, 2, 3]
>>> L[10:20] # 存在しないインデックスを指定すると、空のシーケンスを返す
[]
>>> L[1:1] # 長さ0のスライスも、空のシーケンスを返す
[]
>>> L[3:1] # 長さがマイナスになるようなスライスも、空文字列を返す(空文字列と書いてあるけど、上と同じだよな...?)
[]
>>> L[0:10] # 要素の末尾を超えて指定した場合、最後の要素までを返す
[1, 2, 3]
>>> L[-10:10] # 要素の先頭を超えて指定した場合、先頭の要素から返す
[1, 2, 3]
増分値を指定して要素取得
>>> L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> L[1:10:3] # 開始位置から終了位置の間で、インデックス3飛ばしで取得
[1, 4, 7]
# 増分値として負の値を指定すると、要素を後ろから逆の順番で取得する
>>> L[8:2:-1]
[8, 7, 6, 5, 4, 3]
>>> L[10:1:-3]
[9, 6, 3]
スライス指定の省略
>>> L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> L[:5] # 開始位置を省略(開始位置は0となる)
[0, 1, 2, 3, 4]
>>> L[0::2] # 終了位置を省略(終了位置は10となる)
[0, 2, 4, 6, 8]
# 増分値が負の場合
>>> L[:5:-1] # 開始位置を省略(開始位置は10となる)
[9, 8, 7, 6]
>>> L[10::-2] # 終了位置を省略(終了位置は0となる)
[9, 7, 5, 3, 1]
# 増分値を省略した場合、増分値は1
>>> L[2:5:]
[2, 3, 4]
>>> L[2:5] # 最後の:を省略した形、という解釈。なるほど。
[2, 3, 4]
# 省略ワザあれこれ
>>> L[::2]
[0, 2, 4, 6, 8]
>>> L[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
スライスオブジェクト
# スライス演算の[]の中身はsliceオブジェクトとして作成可能(特定範囲を何度も参照する際便利)
>>> L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> L[slice(1, 10, 3)] # L[1:10:3]と同じ
[1, 4, 7]
>>> L[slice(10)] # L[:10]と同じ
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
スライスを指定した代入
>>> L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> L[1:9] = ['spam', 'ham'] # スライス指定範囲の要素を置き換える、長さは一致していなくても良い
>>> L
[0, 'spam', 'ham', 9]
>>> L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> L[1:1] = ['spam', 'ham'] # 長さ0のスライスの場合、元のリストから要素削除はしない(挿入のみ)
>>> L
[0, 'spam', 'ham', 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> L[3:-3] = [] # 右辺が長さ0の場合、元のリストから要素を削除する
>>> L
[0, 1, 2, 7, 8, 9]
# スライスに1以外の増分値を指定すると、該当要素だけが右辺の値で置き換えられる。かっこいい。
>>> L = [0, 1, 2, 3, 4, 5, 6]
>>> L[1::2] = ['one', 'three', 'five']
>>> L
[0, 'one', 2, 'three', 4, 'five', 6]
# 左辺がリストだからといって、リストじゃないと代入できないというわけではない。
# イテラブルオブジェクトであれば代入できる。
>>> L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> L[5:] = 'spam'
>>> L
[0, 1, 2, 3, 4, 's', 'p', 'a', 'm']
累積代入文
>>> L = [1, 2, 3]
>>> L[2] += 4
>>> L
[1, 2, 7]
>>> L = [0, 1, 2, 3]
>>> L[1:3] += ['spam', 'ham'] # 左辺にスライス指定もできる
>>> L
[0, 1, 2, 'spam', 'ham', 3]
>>> L[3:5] *= 2 # L[3:5]にL[3:5]*2を設定。
>>> L
[0, 1, 2, 'spam', 'ham', 'spam', 'ham', 3]
要素の削除
>>> L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del L[1], L[2]
>>> L
[0, 2, 4, 5, 6, 7, 8, 9]
# もちろんスライスも増分値指定もできる
>>> L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del L[::2]
>>> L
[1, 3, 5, 7, 9]
# 要素の削除は、オブジェクトを開放するわけではない。シーケンスから取り除くだけ。
>>> L1 = [1, 2, 3]
>>> L2 = [L1]
>>> L2
[[1, 2, 3]]
>>> del L2[0]
>>> L2
[]
>>> L1 # L1が削除されるわけではない
[1, 2, 3]
シーケンスの演算子
>>> [1, 2] + [3, 4] # 連結
[1, 2, 3, 4]
>>> [1, 2] * 3 # 指定回数分繰り返し
[1, 2, 1, 2, 1, 2]
>>> 3 * [1, 2] # 演算順序を入れ替えても同様
[1, 2, 1, 2, 1, 2]
# 比較演算子は、シーケンスの要素同士を先頭から比較する
>>> [1, 2] < [3, 4]
True # (1 < 3) & (2 < 4)
# in(メンバーシップ演算子と呼ぶらしい)
>>> 'B' in ['A', 'B', 'C']
True