Python初心者が「Python文法詳解」を読んだメモ #5

# バックナンバー
- [Python初心者が「Python文法詳解」を読んだメモ #1](https://qiita.com/usayomo/items/7024c619c5f72462cb10) 
- [Python初心者が「Python文法詳解」を読んだメモ #2](https://qiita.com/usayomo/items/9c1537678bdde813a273)
- [Python初心者が「Python文法詳解」を読んだメモ #3](https://qiita.com/usayomo/items/57e6156c95e60b3223ca)
- [Python初心者が「Python文法詳解」を読んだメモ #4](https://qiita.com/usayomo/items/01fdb8bbe7704da236bb)

# 第4章 シーケンスとコンテナ型
- Pythonでは、一般に配列と呼ばれる順序付きのコレクションを**シーケンス**と呼ぶ
- リスト型、タプル型、文字列型、バイト型など様々なデータ型があるが、いずれも同様に要素の操作ができる


```py:添字によるアクセス
>>> 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
```

```py:スライス
# インデックス値の範囲を指定して一括で取得
>>> 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]
```

```py:増分値を指定して要素取得
>>> 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]
```

```py:スライス指定の省略
>>> 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]
```

```py:スライスオブジェクト
# スライス演算の[]の中身は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]
```

```py:スライスを指定した代入
>>> 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']
```

```py:累積代入文
>>> 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]
```

```py:要素の削除
>>> 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]
```

```py:シーケンスの演算子
>>> [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
```