- 基本の形は
[式 for 要素 in イテラブル if 条件]です。 - 末尾の単純な
ifは絞り込み、先頭のif-elseは2つの値からの選択です。 - 今回のテストでは、内包表記は
appendを使うループより約37%高速でした。 - 大量のデータにはジェネレータ式を、ロジックが複数の明確な手順を要する場合は通常のループを使いましょう。
Pythonのリスト内包表記は、任意のイテラブルから新しいリストを読みやすい1行で作ります。空のリストを作ってループし、append を呼ぶ代わりに、欲しい結果を記述します。
このガイドでは、基本の形からフィルタ、ネストしたループ、そして私たち自身が測定した処理時間までを説明します。Pythonが初めての方は、まず初心者向けPythonチュートリアル(英語)をご覧ください。環境は仮想環境ガイド(英語)で整えておきましょう。
Pythonのリスト内包表記の構文
左から右へ読みます。式は新しい各要素の形を表し、for の部分は要素の取得元を表します。
squares = [x * x for x in range(6)]
print(squares) # [0, 1, 4, 9, 16, 25]
names = [" Hi ", " QA "]
clean = [n.strip().lower() for n in names]
print(clean) # ['hi', 'qa']
同じ結果をループで書くと3行多くなります。1行が読みやすいままである限り、この短さが利点です。
条件で要素を絞り込む
ループの後ろに if を付けると、条件を満たす要素だけが残ります。
evens = [x for x in range(10) if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8]
if-else を使ったリスト内包表記
すべての要素に対して値を出したいときは、if-else を for の前に置きます。末尾に else を置くと構文エラーになるため、初心者が最もつまずく部分です。
labels = ["even" if x % 2 == 0 else "odd" for x in range(4)]
print(labels) # ['even', 'odd', 'even', 'odd']
目安:末尾の if は要素を取り除き、先頭の if-else は要素を変えます。if-else ではリストの長さは変わりません。
ネストしたループと平坦化
複数の for 節は、ネストしたループと同じ順序で読みます。リストのリストを平坦化したり、ペアを作ったりするのに使えます。
matrix = [[1, 2, 3], [4, 5, 6]]
flat = [n for row in matrix for n in row]
print(flat) # [1, 2, 3, 4, 5, 6]
pairs = [(x, y) for x in range(1, 3) for y in "ab"]
print(pairs) # [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
行列を転置するには、内包表記を別の内包表記の中に入れます。[[r[i] for r in matrix] for i in range(3)] は [[1, 4], [2, 5], [3, 6]] になります。読みやすさが落ちない実用上の限界は2段までです。
辞書・集合・ジェネレータの形
括弧を変えるだけで、同じ考え方が他の型を作ります。
lengths = {w: len(w) for w in ["pip", "venv", "uv"]} # {'pip': 3, 'venv': 4, 'uv': 2}
unique = {len(w) for w in ["pip", "venv", "uv", "git"]} # {2, 3, 4}
total = sum(x * x for x in range(1_000_000)) # generator, no list
型そのものの比較は、リスト・タプル・集合・辞書のガイド(英語)をご覧ください。
速度とメモリ:私たちの実測結果
Python 3.13.6 で100,000個の整数を使い、各方式を5回実行した最良値を採用しました。数値は環境によって変わりますが、順位は安定しています。
| 処理 | 時間 |
|---|---|
append を使うループ(各要素を2倍) | 5.18 ms |
| リスト内包表記(各要素を2倍) | 3.25 ms |
list(map(lambda ...)) | 6.50 ms |
| ループで偶数を抽出 | 3.62 ms |
| 内包表記で偶数を抽出 | 3.43 ms |
内包表記は append のループを明確に上回りますが、時間の大半が条件判定にかかる場合は差が縮まります。メモリ面では、2倍にした100万個の整数のリストは約8.4 MBでしたが、同じ内容のジェネレータオブジェクトは200バイトでした。値を1つずつ生成するためです。
リスト内包表記を使うべきでない場面
- 表示や保存などの副作用だけが目的のとき。通常のループを使いましょう。内包表記では不要なリストが作られます。
- ロジックが複数の手順に分かれるとき。2つ目の変数や
tryが必要なら、ループや小さな関数にします。 - データが非常に大きいとき。ジェネレータ式を使えば、Pythonはリスト全体をメモリに保持しません。
- 3つ以上の
for節が必要なとき。次に読む人のために、名前付きの手順に分けましょう。
まとめ
短い1行で意図が正確に伝わるならPythonのリスト内包表記を、そうでなければループを使いましょう。基本の形から始め、フィルタを加え、順序が自然に感じられるまで if-else の形を練習してください。
よくある質問
Pythonのリスト内包表記とは何ですか?
イテラブルの各要素に式を適用してリストを作る簡潔な書き方で、条件を付けて絞り込むこともできます。
リスト内包表記で if-else はどう使いますか?
条件式を for 節の前に置きます。例:["even" if x % 2 == 0 else "odd" for x in nums]。単純な絞り込みはループの後ろに if を1つ置くだけです。
リスト内包表記は for ループより速いですか?
多くの場合は速いです。100,000要素のテストでは append を使うループより約37%高速でしたが、まず読みやすさで判断しましょう。
リスト内包表記とジェネレータ式の違いは何ですか?
リスト内包表記はリスト全体を一度にメモリ上に作ります。ジェネレータ式は丸括弧を使い、値を1つずつ生成するため、大きなデータではメモリを節約できます。
リスト内包表記はネストできますか?
はい、行列の平坦化や転置に使えます。2段までにとどめ、読みにくくなったらループに切り替えましょう。
さらに学ぶ(英語の記事)
テスト、WordPress、SEOでお困りですか?
私たちは、チームがより良いソフトウェアを提供し、サイトを成長させるお手伝いをしています。取り組んでいる内容をお知らせいただければ、明確な次のステップをご提案します。
詳しいガイドはこちら テスト、AI、最新の開発
この記事は気に入りましたか?トピックを選択して、最新のチュートリアルに直接アクセスしてください。
AI 幻覚の説明: 言語モデルが物事をでっち上げる理由とそれを軽減する方法
AI 幻覚について説明しました。幻覚とは何か、言語モデルが幻覚を生成する理由、一般的な種類、グラウンディングとプロンプトで幻覚を軽減する方法、そして私たちが実行した簡単なチェックです。
記事を読む →DevOps環境変数の説明: .env ファイル、シークレット、および設定が正しく行われている
実行した Python の例を使用して環境変数について説明します。環境変数の読み取りと設定、すべての値が文字列である理由、.env ファイル、プロセスの継承、シークレット、検証について説明します。
記事を読む →ソフトウェア開発API レート制限の説明: アルゴリズム、ヘッダー、および 429 エラーの処理
API レート制限については、実行したシミュレーションで説明します。トークン バケット、固定ウィンドウ、スライディング ウィンドウ、429 応答、レート制限ヘッダー、バックオフによる再試行、およびテスト制限です。
記事を読む →テスト自動化Python でのモッキング:unittest.mock、patch、およびテストを嘘にする間違い
Python でのunittest.mockによるモック、テスト済み: モックとreturn_value、side_effect、名前が使用されている場所のパッチ、仕様と自動仕様、日付のモック、およびよくある間違い。
記事を読む →ソフトウェアテストコードカバレッジの説明: 回線カバレッジとブランチカバレッジ、および 100% の実際の意味
実際のcoverage.pyの実行でコードカバレッジを説明: 行、分岐、条件のカバレッジ、レポートの読み取り、100%のカバレッジでもバグを見逃す可能性がある理由、および賢明なターゲット。
記事を読む →データベースとSQLSQL における DELETE、TRUNCATE、DROP: 違い、ロールバック、およびそれぞれをいつ使用するか
DELETE、TRUNCATE、DROP について、テスト済み SQL を使用して説明します。それぞれの削除内容、ロールバック、トリガー、ID リセット、速度、PostgreSQL、MySQL、SQL Server、SQLite の違いについて説明します。
記事を読む →データベースとSQLSQL ビューの説明: 作成、使用、落とし穴の回避、例を示します
SQL ビューについて、実行したクエリとともに説明しました。ビューの作成、ライブ結果、列の非表示、パフォーマンス、更新可能なビューと具体化されたビュー、壊れた依存関係、ベスト プラクティスについて説明します。
記事を読む →ソフトウェア開発TypeScript インターフェイスと型: 実際の違い、コンパイラでテスト
TypeScript インターフェイスと型、実際のコンパイラでチェック: 両方でできること、片方だけでできること、宣言のマージ、拡張と交差、および従うべき簡単なルール。
記事を読む →ソフトウェア開発Python *args と **kwargs の説明: 柔軟な関数と明確な例
Python の *args と **kwargs について、実行したコードで説明しました。パッキングとアンパッキング、パラメーターの順序、キーワードのみの引数と位置のみの引数、デコレーター、一般的なエラーです。
記事を読む →ソフトウェア開発Python Lambda 関数: 構文、実際の用途、および使用すべきでない場合
Python のラムダ関数について、実行したコードとともに説明します。構文、キーによるソート、マップとフィルター、クロージャー、遅延バインディング トラップ、通常の def がより適切な選択である場合。
記事を読む →人工知能AIエージェントとは何ですか?シンプルなエージェント ループを実行できる仕組み
AIエージェントとは何ですか?エージェント ループ、ツール、メモリ、ガードレール、実行した小さな Python ループ、実際のリスク、およびシンプルなチャットボットがより良い選択である場合についてのわかりやすいガイドです。
記事を読む →DevOpsモニタリングと可観測性: ログ、メトリクス、トレースによる本当の違い
モニタリングと可観測性について説明: 既知および未知の障害、ログ、メトリクスとトレース、チェックアウト インシデントのウォークスルー、ゴールデン シグナル、OpenTelemetry、および便利なアラート。
記事を読む →DevOpsDocker ボリュームとバインド マウント: コンテナ データを正しい方法で保持する
Docker ボリュームとバインド マウントについて説明します。コンテナ データが消える理由、名前付きボリューム、バインド マウント、tmpfs、Compose の例、バックアップ、アクセス許可、およびそれぞれをいつ使用するかについて説明します。
記事を読む →テスト自動化TDD と BDD: 主な違い、1 つの機能が両方の方法で構築され、それぞれをいつ使用するか
TDD と BDD は、両方の方法で構築された 1 つの割引機能で説明されています。実行したコードによるレッド-グリーン-リファクタリング、Given-When-Then シナリオ、ツール、トレードオフ、およびそれぞれをいつ使用するかです。
記事を読む →ソフトウェア開発Git mergeとrebaseの違い:例と使い分け
Git mergeとrebaseの違いを、実際のログ出力、比較表、rebaseの黄金律、安全なチームワークフローで解説します。
記事を読む →ソフトウェア開発Pythonのリスト内包表記:構文・例・使うべきでない場面
Pythonのリスト内包表記を解説:構文、フィルタ、if-else、ネストしたループ、実測した処理時間、そして通常のforループの方が良い場面。
記事を読む →データベースとSQLSQL JOINを例で解説(Inner・Left・Right・Full)
サンプルのテーブルとクエリでSQL JOINを順に解説。INNER、LEFT、RIGHT、FULL、CROSS、SELFに加え、よくある間違いとパフォーマンスのコツも紹介します。
記事を読む →