# Pythonのリスト（list）：メソッド、スライス、ソート、append、タプルと集合

URL: https://skillaria.top/ja/guides/python/spiski-python

Pythonのリスト（list）は、角かっこで囲んで書く、順序があり変更できる値の並びです。例えば [250, 1200, 99] のように書きます。要素はappendで追加し、挿入、削除、スライスによる取り出し、並べ替えができます。sortメソッドはリストをその場で並べ替えてNoneを返し、sorted関数は新しい並べ替え済みのリストを返します。

Pythonのリスト（`list`）は、角かっこで囲んだ値の並びで、中身を変更できます。末尾に要素を追加し、途中に挿入し、削除し、並べ替えられます。言語の中で最もよく使われるコレクションで、ファイルの行、月の支出、APIの応答など、多くのデータがリストとして扱われます。ここではPythonのリストを一通り見ていきます。作成、メソッド、スライス、並べ替え、リスト内包表記、コピーを扱い、最後にタプルと集合を紹介します。

## Pythonのリストとは

リストは要素を指定した順序で保持し、0から始まる番号（インデックス）で要素にアクセスします。1つのリストに異なる型の値を入れることもできますが、実際には同じ種類のデータをまとめて扱うことが多いです。

```
amounts = [250, 1200, 99]
print(amounts[0])     # 250 — 最初の要素
print(amounts[-1])    # 99 — 最後の要素
amounts[1] = 1300     # リストは変更できる
print(len(amounts))   # 3 — リストの長さ
```

リストの長さは `len()` 関数で求めます。存在しないインデックスを指定すると、`IndexError: list index out of range` が発生します。

## リストの作成

```
empty = []                       # 空のリスト
also_empty = list()              # list 関数で作成しても同じ
nums = [1, 2, 3]
chars = list("abc")              # ['a', 'b', 'c']
digits = list(range(5))          # [0, 1, 2, 3, 4]
zeros = [0] * 4                  # [0, 0, 0, 0]
```

`list()` 関数は、文字列、`range`、集合、辞書のキーなど、繰り返し可能なオブジェクトをリストに変換します。

## appendとその他のリストメソッド

`append` は、要素を1つ末尾に追加するメソッドです。Pythonで最もよく使われるメソッドの1つです。リストをその場で変更し、戻り値は `None` です。

```
amounts = [250, 1200]
amounts.append(450)          # [250, 1200, 450]
amounts.extend([10, 20])     # [250, 1200, 450, 10, 20]
amounts.insert(0, 5)         # [5, 250, 1200, 450, 10, 20]
amounts.remove(1200)         # 最初の値 1200 を削除
last = amounts.pop()         # 20 — 最後の要素を削除して返す
```

よくあるミスは、`a.append([10, 20])` と書くことです。これは2つの数字ではなく、1つの要素（入れ子のリスト）を追加します。複数の要素を追加するには `extend` を使います。

| メソッド | 役割 |
| --- | --- |

| `append(x)` | x を末尾に追加 |

| `extend(iter)` | 並びの全要素を追加 |

| `insert(i, x)` | インデックス i の前に x を挿入 |

| `remove(x)` | 最初に現れる x を削除（なければ ValueError） |

| `pop(i=-1)` | インデックス i の要素を削除して返す |

| `index(x)` | x が最初に現れる位置 |

| `count(x)` | x の出現回数 |

| `sort()` | その場で並べ替え |

| `reverse()` | その場で逆順にする |

| `copy()` | 浅いコピーを作る |

| `clear()` | リストを空にする |

インデックスや範囲を指定して削除するには `del` 文も使えます。例：`del a[0]`、`del a[1:3]`。リストに使える組み込み関数には、`len`、`sum`、`min`、`max`、`sorted`、`reversed`、`enumerate`、`zip` があります。

## Pythonのスライス

スライスは `a[start:stop:step]` の形でリストの一部を取り出します。`start` は含まれ、`stop` は含まれず、`step` ごとに取り出します。どの部分も省略できます。スライスは必ず新しいリストを返します。

```
a = [0, 1, 2, 3, 4, 5]
print(a[1:4])     # [1, 2, 3]
print(a[:2])      # [0, 1] — 最初の2つ
print(a[-2:])     # [4, 5] — 最後の2つ
print(a[::2])     # [0, 2, 4] — 1つおき
print(a[::-1])    # [5, 4, 3, 2, 1, 0] — 逆順
print(a[:])       # リスト全体のコピー
```

インデックスと違い、リストの範囲外を指定したスライスはエラーになりません。`a[10:20]` は単に `[]` を返します。スライスに値を代入して、リストの一部を置き換えることもできます。例：`a[1:3] = ["x", "y", "z"]`。

### 文字列のスライス

スライスは、文字列やタプルなど、どの並びに対しても同じように使えます。

```
s = "Python 3.15"
print(s[:6])      # Python
print(s[-4:])     # 3.15
print(s[::-1])    # 51.3 nohtyP
```

文字列はスライスで変更できません。文字列は変更不可能で、スライスは新しい文字列を作るだけです。

## リストの並べ替え：sortとsorted

ここは初心者が最も混乱しやすい部分です。`sort` メソッドはリスト自体の要素を並べ替え、戻り値は `None` です。一方、`sorted` 関数は元のリストに触れず、並べ替えた新しいリストを返します。

```
amounts = [250, 1200, 99]
amounts.append(450)
print(sorted(amounts))     # [99, 250, 450, 1200] — 新しいコピー
print(amounts)             # [250, 1200, 99, 450] — 元のリストはそのまま

result = amounts.sort()    # その場で並べ替え
print(result, amounts)     # None [99, 250, 450, 1200]
```

ここから「なぜ None になるのか」という典型的な問題が生まれます。`a = a.sort()` と書くと、リストが `None` で上書きされてしまいます。`a.sort()` と書くか、`a = sorted(a)` と書きましょう。

### キーと逆順

どちらの方法も `key` と `reverse` という引数を受け取ります。`key` は、要素を比較するための値を計算する関数です。

```
words = ["coffee", "Taxi", "subscription"]
print(sorted(words, key=len))               # ['Taxi', 'coffee', 'subscription']
print(sorted(words, key=str.lower))         # 大文字・小文字を区別せずに並べ替え
print(sorted([3, 1, 2], reverse=True))      # [3, 2, 1]

expenses = [("食費", 650), ("映画", 120), ("タクシー", 300)]
expenses.sort(key=lambda e: e[1])           # 金額順
```

Pythonのソートは安定しています。同じキーを持つ要素は、元の順序を保ちます。また、`sorted` は文字列、辞書、集合など、どの並びでも使えますが、`sort` メソッドはリストだけのメソッドです。

## リストを逆順にする

方法は3つあり、動作が異なります。

- `a.reverse()` ― その場で逆順にし、戻り値は `None`。
- `a[::-1]` ― 逆順になった新しいリストを作る。
- `reversed(a)` ― 遅延評価のイテレータ。ループで便利です。例：`for x in reversed(a):`。

## リストのループ

```
items = ["コーヒー", "電車", "映画"]
for item in items:
    print(item)

for i, item in enumerate(items, start=1):
    print(i, item)          # 1 コーヒー、2 電車、3 映画

print("映画" in items)      # True — 要素が含まれるかの確認
```

ループしているリストから要素を削除しないでください。一部の要素が飛ばされてしまいます。リスト内包表記で新しいリストを作るか、コピー `a[:]` をループしましょう。

## リスト内包表記

リスト内包表記（list comprehension）は、式、ループ、省略可能な条件を1行に書いて新しいリストを作ります。

```
squares = [n * n for n in range(6)]          # [0, 1, 4, 9, 16, 25]
big = [a for a in [250, 1200, 99] if a > 200]  # [250, 1200]
names = [s.strip().title() for s in [" anna ", "oleg"]]
```

リスト内包表記は、`append` を使うループより速く、読みやすいことが多いです。ただし、処理が1行で分かりやすく書けないなら、普通のループの方が良い選択です。

## リストの結合、連結、差分

```
a = [1, 2, 3]
b = [3, 4]
print(a + b)       # [1, 2, 3, 3, 4] — 新しいリスト
a += b             # a.extend(b) と同じ
print([*a, *b])    # アンパックで新しいリストを作る
```

リストに `-` 演算子はありません。1つのリストから別のリストの要素を取り除きたいときは、内包表記を使います。例：`[x for x in a if x not in set(b)]`。2つのリストの共通部分は、集合を使うと簡単に求められます。例：`set(a) & set(b)`（順序と重複は失われます）。

## 入れ子のリストと二次元リスト

リストのリストは、表や行列を保持する簡単な方法です。

```
matrix = [[1, 2, 3], [4, 5, 6]]
print(matrix[1][2])     # 6
grid = [[0] * 3 for _ in range(2)]   # 正しい書き方
bad = [[0] * 3] * 2                  # 落とし穴：同じリストへの参照が2つ
bad[0][0] = 9
print(bad)              # [[9, 0, 0], [9, 0, 0]]
```

## リストのアンパック

```
first, second, third = [10, 20, 30]
head, *rest = [1, 2, 3, 4]      # head=1, rest=[2, 3, 4]
print(*["a", "b"], sep=", ")    # a, b — 角かっこなしで表示
```

変数の数がリストの長さと合わないと `ValueError` が出ます。そのようなときは、アスタリスクが役立ちます。

## リストのコピー

`b = a` はリストをコピーしません。同じオブジェクトに2つ目の名前を付けるだけです。そのため、`b` を変更すると `a` も変わります。独立したコピーを作るには、明示的に `a.copy()`、`list(a)`、または `a[:]` を使います。入れ子のデータでは、これだけでは不十分です。内側のリストは共有されたままになるため、`copy.deepcopy(a)` が必要です。

```
import copy
a = [[1, 2], [3]]
b = a.copy()
b[0].append(99)
print(a)                 # [[1, 2, 99], [3]] — 内側のリストは共有されている
c = copy.deepcopy(a)     # 完全に独立したコピー
```

## タプル：変更できないリスト

タプル（`tuple`）はリストに似ていますが、作成後は変更できません。これは読み手に対する明確なメッセージです。固定の項目を持つ1つのレコードであり、増えていく集まりではない、ということです。タプルは簡単にアンパックでき、関数が複数の値を返すときにもよく使われます。

```
expense = (250, "コーヒー")
amount, item = expense
expense[0] = 300
# TypeError: 'tuple' object does not support item assignment
```

変更できない値だけからなるタプルはハッシュ可能なので、辞書のキーに使えます。要素が1つだけのタプルは、カンマを付けて書きます。例：`(5,)`。

## 集合：一意の値だけ

集合（`set`）は一意な値だけを保持し、順序は覚えません。重複を取り除くことや「その要素があるか」の確認が最も速くできる方法で、和集合、積集合、差集合も扱えます。

```
jan = {"食費", "タクシー", "映画"}
feb = {"食費", "サブスク"}
print(jan & feb)    # {'食費'}
print(feb - jan)    # {'サブスク'}
unique = list(dict.fromkeys([3, 1, 3, 2]))   # [3, 1, 2] — 重複を除き、順序を保持
empty = set()       # {} は空の dict です！
```

## どのコレクションを選ぶか

| 用途 | コレクション |
| --- | --- |

| 順序があり、変更もする | `list` |

| 項目が固定のレコード | `tuple` |

| キーで検索する | `dict` |

| 一意性、「含まれるか」の確認 | `set` |

| 変更できない設定 | `frozendict`（Python 3.15） |

`x in list` は要素を先頭から順に調べますが、`x in set` はほぼ一瞬で結果が出ます。大きなリストへの「含まれるか」の確認をループの中で何度も行うなら、集合に変換しましょう。

## まとめ

Pythonのリストは、順序があり変更できるコレクションです。`append` と `extend` で追加し、`pop` と `remove` で削除します。スライス `a[start:stop:step]` で一部を取り出し、`sort` はその場で並べ替えて `None` を返し、`sorted` は新しいリストを返します。コピーは明示的に作り、固定のレコードにはタプル、一意な値には集合を使いましょう。リスト、タプル、辞書、集合は、講座「Python 3.15：初心者からプロへ」の実践的な講義で扱っています。

## FAQ

**Pythonのリストと配列の違いは何ですか？**

Pythonには他の言語のような組み込みの配列はありません。その役割はリストが担い、異なる型の値を混在させることもできます。数値だけをコンパクトに扱いたいときは、標準の array モジュールやNumPyを使います。

**リストの中で要素の位置を調べるにはどうしますか？**

a.index(x) は最初に現れる位置を返します。要素がないと ValueError になるので、呼び出す前に x in a で確認しましょう。

**順序を保ったままリストの重複を削除するにはどうしますか？**

list(dict.fromkeys(a)) を使います。辞書はキーを一意に保ち、挿入順を覚えています。list(set(a)) でも重複は消えますが、順序は保たれません。

**文字列のリストを1つの文字列にするにはどうしますか？**

文字列のメソッド join を使います。例：", ".join(["a", "b", "c"]) は "a, b, c" になります。すべての要素が文字列である必要があるので、数値は先に map(str, a) で変換します。

**リストに異なる型の要素を入れてもよいですか？**

はい。数字、文字列、別のリスト、任意のオブジェクトを同時に入れられます。ただし、key 引数なしで並べ替えると、数字と文字列の比較は TypeError になるため、通常は避けましょう。


---
Source: Skillaria.Top (https://skillaria.top)
