Pythonのリスト内包表記とは、for文で処理した結果から新しいリストを作る短い書き方です。
たとえば、数値の一覧から2倍した一覧を作る、条件に合う値だけを取り出す、といった処理を1行で表せます。

最初は『短く書けるfor文』ではなく、『新しいリストを作る構文』として読むと混乱しにくくなります。
この記事では、for文でappendする書き方との違い、基本形、if条件の付け方、読みやすく使うための判断を解説します。
次の図では、リスト内包表記を元のリストから要素を流し、条件ゲートと加工ゲートを通して新しいリストを作るラインとして見てください。

次の図では、通常のfor文で行っていた『取り出す・加工する・入れる』が、リスト内包表記の1行へまとまるイメージを見てください。

まず結論:新しいリストを作るための構文
Python公式チュートリアルでは、リスト内包表記はリストを作る簡潔な方法として紹介され、別の並びから各要素を加工したリストや条件に合う部分リストを作る用途が説明されています。
for文で書く場合
まずは通常のfor文で、新しいリストを作る例を見ます。
numbers = [1, 2, 3, 4]
squares = []
for number in numbers:
squares.append(number * number)
print(squares) # [1, 4, 9, 16]
このコードでは、元のリストから1件ずつ取り出し、計算結果をappendで新しいリストへ追加しています。リストの基本が曖昧な場合は、Pythonのリストを先に確認してください。
リスト内包表記で書く場合
同じ処理をリスト内包表記で書くと、次のようになります。
numbers = [1, 2, 3, 4]
squares = [number * number for number in numbers]
print(squares) # [1, 4, 9, 16]
読み方は、for number in numbersで1件ずつ取り出し、左側のnumber * numberを新しいリストへ入れる、です。
基本形を分けて読む
リスト内包表記の基本形は、次のように分けると読みやすくなります。
[作る値 for 要素 in 元の並び]
| 部分 | 役割 | 例 |
|---|---|---|
| 作る値 | 新しいリストに入れる値 | number * number |
| 要素 | 1件ずつ取り出す変数 | number |
| 元の並び | 取り出し元のリストなど | numbers |
for文そのものの読み方はPythonのfor文、連番を作る処理はrange関数と合わせて押さえると整理できます。
ifで条件を付ける
条件に合う要素だけを使いたい場合は、最後にifを付けます。
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = [number for number in numbers if number % 2 == 0]
print(even_numbers) # [2, 4, 6]
この例では、number % 2 == 0を満たす偶数だけを新しいリストに入れています。
加工と絞り込みを同時に行う
リスト内包表記では、値を加工しながら条件で絞ることもできます。
names = ["sato", "suzuki", "tanaka"]
upper_s_names = [name.upper() for name in names if name.startswith("s")]
print(upper_s_names) # ['SATO', 'SUZUKI']
ここでは、sで始まる名前だけを取り出し、upper()で大文字に変換しています。
for文とどちらを使うべきか
| 場面 | おすすめ | 理由 |
|---|---|---|
| 単純に新しいリストを作る | リスト内包表記 | 短く、目的が見えやすい |
| 処理が複数行になる | 通常のfor文 | 途中の処理を説明しやすい |
| 副作用がある処理 | 通常のfor文 | printやファイル書き込みは目的が違う |
| 条件が複雑 | 通常のfor文または変数に分ける | 読み間違いを防げる |
短ければ常に良いわけではありません。読んだ人がすぐ意味を追える範囲で使うのが大切です。
lambdaやmapとの関係
Pythonでは、mapやlambdaを使って似た処理を書くこともあります。
numbers = [1, 2, 3]
result = list(map(lambda x: x * 2, numbers))
ただし、初心者がまず覚えるなら、リスト内包表記の方が『何を取り出して、何を作るか』を読み取りやすい場面が多いです。lambdaの基本はPythonのラムダ関数で扱っています。
初心者がつまずきやすいポイント
| つまずき | まずこう理解する |
|---|---|
| 左から順番に読もうとして混乱する | 先にfor ... in ...を見て、次に左側を見る |
| 何でも1行にまとめる | 複雑なら通常のfor文へ戻す |
| 元のリストが変わると思う | 基本は新しいリストを作る |
| print目的で使う | リストを作らない処理には向かない |
読み方は右から左へ確認する
リスト内包表記は、見た目は左から始まりますが、読むときはforの部分から確認すると分かりやすくなります。
result = [name.upper() for name in names if len(name) >= 5]
この例は、まずfor name in namesで名前を1件ずつ取り出し、次にif len(name) >= 5で5文字以上に絞り、最後にname.upper()を新しいリストへ入れる、と読みます。
ネストした内包表記は最初は避ける
リスト内包表記は入れ子にもできますが、初心者のうちは無理に使わない方が読みやすいです。
# 読みにくくなりやすい例
pairs = [(x, y) for x in range(3) for y in range(3)]
# 最初はfor文で展開して理解する
pairs = []
for x in range(3):
for y in range(3):
pairs.append((x, y))
短いコードでも、読む人がすぐに処理の順番を追えなければメリットが薄くなります。二重ループや複雑な条件が出てきたら、通常のfor文へ戻す判断も大切です。
元のリストは基本的に変えない
リスト内包表記は、新しいリストを作るための構文です。元のリストの中身を書き換える処理ではありません。
numbers = [1, 2, 3]
doubled = [number * 2 for number in numbers]
print(numbers) # [1, 2, 3]
print(doubled) # [2, 4, 6]
元の値を残したまま、加工後の一覧を別に持てるのは大きな利点です。元のリストも変えたい場合は、代入やスライス、通常のfor文など、別の書き方を検討します。
練習するときの題材
リスト内包表記は、単純な変換と絞り込みから練習すると理解しやすいです。
いきなり複雑な処理に使うより、for文で書ける処理をリスト内包表記へ置き換える練習をすると、構文の対応関係が見えやすくなります。
実務コードでの使いどころ
リスト内包表記は、データの一覧を画面表示用に加工したり、APIから受け取ったリストの一部だけを取り出したり、ファイル名の一覧を整形したりする場面でよく使われます。どれも共通しているのは、『元の並びから新しいリストを作る』という目的がはっきりしていることです。
逆に、途中でログを出す、複数の変数を更新する、例外処理を細かく入れる、といった処理は通常のfor文の方が向いています。リスト内包表記は、処理の目的が1つに絞れるときに使うと読みやすくなります。
公式情報と関連して読みたい記事
まとめ
リスト内包表記は、for文で処理した結果から新しいリストを作るための構文です。
リスト内包表記を読めるようになると、Pythonらしいリスト処理のコードがかなり追いやすくなります。
