この記事で解決すること
「リスト内包表記って何?普通のfor文と何が違うの?」
リスト内包表記の読み方・書き方・使いどころを、for文との比較で解説します。Pythonの環境構築がまだの方は、Python仮想環境(venv)の使い方を先に読んでおくとスムーズです。
リスト内包表記とは
「リストを1行で作る書き方」です。
for文で書く場合
# 1〜5の2乗のリストを作る
squares = []
for i in range(1, 6):
squares.append(i ** 2)
print(squares) # [1, 4, 9, 16, 25]
3行かかります。
リスト内包表記で書く場合
# 同じことを1行で
squares = [i ** 2 for i in range(1, 6)]
print(squares) # [1, 4, 9, 16, 25]
1行で同じ結果が得られます。パッケージのインストールでエラーが出た場合はpip installでエラーが出たときの対処法を確認してみてください。
基本の構文
[式 for 変数 in イテラブル]
日本語に訳すと:
[「変数を使った計算」 を 「イテラブルの各要素」 について繰り返す]
読み方のコツ
右から左に読むと分かりやすいです。
[i * 2 for i in range(5)]
# ↑ ↑
# 何をする 何を繰り返す
#
# range(5)の各iについて → i * 2 を計算 → リストにする
パターン別の使い方
パターン1: 変換する
# 文字列のリストを大文字に変換
names = ["alice", "bob", "charlie"]
upper_names = [name.upper() for name in names]
print(upper_names) # ['ALICE', 'BOB', 'CHARLIE']
for文で書くと:
upper_names = []
for name in names:
upper_names.append(name.upper())
パターン2: フィルタする(if付き)
# 偶数だけを抽出
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = [n for n in numbers if n % 2 == 0]
print(evens) # [2, 4, 6, 8, 10]
構文:
[式 for 変数 in イテラブル if 条件]
for文で書くと:
evens = []
for n in numbers:
if n % 2 == 0:
evens.append(n)
パターン3: 変換 + フィルタ
# 偶数だけを2乗する
numbers = [1, 2, 3, 4, 5, 6]
result = [n ** 2 for n in numbers if n % 2 == 0]
print(result) # [4, 16, 36]
パターン4: if-else付き
# 偶数なら"偶数"、奇数なら"奇数"
numbers = [1, 2, 3, 4, 5]
labels = ["偶数" if n % 2 == 0 else "奇数" for n in numbers]
print(labels) # ['奇数', '偶数', '奇数', '偶数', '奇数']
注意:if-elseの場合は for の前に書きます。ifだけの場合は for の後です。
# ifだけ(フィルタ)→ forの後
[n for n in numbers if n > 3]
# if-else(変換)→ forの前
["大" if n > 3 else "小" for n in numbers]
実践例
例1: CSVデータの処理
# カンマ区切りの文字列を数値リストに変換
csv_line = "85,92,78,95,88"
scores = [int(s) for s in csv_line.split(",")]
print(scores) # [85, 92, 78, 95, 88]
print(sum(scores)) # 438
例2: ファイル名のフィルタ
import os
# カレントディレクトリの.pyファイルだけ取得
py_files = [f for f in os.listdir(".") if f.endswith(".py")]
print(py_files)
ファイル操作の自動化に興味がある方は、Pythonでファイル整理を自動化する方法も参考にしてみてください。
例3: 辞書からの抽出
users = [
{"name": "田中", "age": 25, "active": True},
{"name": "鈴木", "age": 30, "active": False},
{"name": "佐藤", "age": 22, "active": True},
]
# アクティブなユーザーの名前だけ取得
active_names = [u["name"] for u in users if u["active"]]
print(active_names) # ['田中', '佐藤']
使わない方がいい場面
リスト内包表記は万能ではありません。以下の場合はfor文の方が読みやすいです。正規表現を使った複雑なフィルタリングなどは、正規表現入門を参考にしつつ、for文で書いた方が可読性が高くなります。
NG: 複雑すぎる処理
# これは読みにくい(やめた方がいい)
result = [x * 2 + 1 for x in range(100) if x % 3 == 0 and x % 5 != 0 and x > 10]
# for文で書いた方が分かりやすい
result = []
for x in range(100):
if x % 3 == 0 and x % 5 != 0 and x > 10:
result.append(x * 2 + 1)
NG: 副作用がある処理
# これはNG(リスト内包表記の目的外使用)
[print(x) for x in range(5)]
# 普通のfor文を使う
for x in range(5):
print(x)
判断基準
| 状況 | 使うべき書き方 |
|---|---|
| 単純な変換・フィルタ | リスト内包表記 |
| 1行で読める | リスト内包表記 |
| 条件が複雑 | for文 |
| 副作用がある(print, ファイル書き込み等) | for文 |
| ネストが2段以上 | for文 |
よくある質問(FAQ)
Q: リスト内包表記と map() / filter() はどちらを使うべきですか?
A: Pythonでは一般的にリスト内包表記の方が読みやすいとされています。特に条件付きのフィルタリングでは、リスト内包表記の方がシンプルに書けます。ただし、既存の関数をそのまま適用する場合(例: list(map(int, strings)))は map() の方が簡潔なこともあります。
Q: リスト内包表記はメモリを大量に使いますか?
A: リスト内包表記は結果をすべてメモリに保持するため、大量のデータ(数百万件以上)を扱う場合はメモリ不足になる可能性があります。その場合は、ジェネレータ式 (式 for 変数 in イテラブル) を使うと、要素を1つずつ生成するのでメモリ効率が良くなります。
Q: 辞書やセットでも内包表記は使えますか?
A: はい、使えます。辞書内包表記は {key: value for 変数 in イテラブル}、セット内包表記は {式 for 変数 in イテラブル} と書きます。リスト内包表記と同じ感覚で使えます。
Q: ネストした(2重の)リスト内包表記は使ってもいいですか?
A: 技術的には可能ですが、読みにくくなるため推奨しません。2重ループが必要な場合は、通常のfor文で書いた方がチームメンバーにも理解しやすいコードになります。
Q: リスト内包表記の中でインデックス番号を使いたい場合はどうしますか?
A: enumerate() を組み合わせます。例: [f"{i}: {name}" for i, name in enumerate(names)] のように書くと、インデックス付きのリストが作れます。
まとめ
- リスト内包表記は「リストを1行で作る書き方」
[式 for 変数 in イテラブル]が基本構文ifを付けてフィルタ、if-elseで条件分岐もできる- 複雑になりすぎたらfor文に戻す。読みやすさが最優先
あわせて読みたい
関連リソース
Pythonをもっと学びたい方へ: