PR

【Python】リスト内包表記とは?for文との違いを初心者向けに解説

unDraw準拠のチェック済みリスト風イラストを使ったPythonリスト内包表記記事のアイキャッチ画像 Python

Pythonのリスト内包表記とは、for文で処理した結果から新しいリストを作る短い書き方です。

たとえば、数値の一覧から2倍した一覧を作る、条件に合う値だけを取り出す、といった処理を1行で表せます。

最初は『短く書けるfor文』ではなく、『新しいリストを作る構文』として読むと混乱しにくくなります。

この記事では、for文でappendする書き方との違い、基本形、if条件の付け方、読みやすく使うための判断を解説します。

次の図では、リスト内包表記を元のリストから要素を流し、条件ゲートと加工ゲートを通して新しいリストを作るラインとして見てください。

元のリストの要素が条件ゲートと加工ゲートを通り新しいリストに入るリスト内包表記のイメージ図
リスト内包表記は、元のリストを1件ずつ流し、必要なら絞り、加工して新しいリストを作る処理です。

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

for文の取り出す加工する入れるという3つの部品がリスト内包表記の1行にまとまることを示す説明図
リスト内包表記は、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では、maplambdaを使って似た処理を書くこともあります。

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文など、別の書き方を検討します。

練習するときの題材

リスト内包表記は、単純な変換と絞り込みから練習すると理解しやすいです。

  • 数値リストを2倍した新しいリストを作る
  • 文字列リストから3文字以上だけを取り出す
  • 名前の一覧をすべて大文字にする
  • 1から10までの偶数だけをリストにする

いきなり複雑な処理に使うより、for文で書ける処理をリスト内包表記へ置き換える練習をすると、構文の対応関係が見えやすくなります。

実務コードでの使いどころ

リスト内包表記は、データの一覧を画面表示用に加工したり、APIから受け取ったリストの一部だけを取り出したり、ファイル名の一覧を整形したりする場面でよく使われます。どれも共通しているのは、『元の並びから新しいリストを作る』という目的がはっきりしていることです。

逆に、途中でログを出す、複数の変数を更新する、例外処理を細かく入れる、といった処理は通常のfor文の方が向いています。リスト内包表記は、処理の目的が1つに絞れるときに使うと読みやすくなります。

公式情報と関連して読みたい記事

まとめ

リスト内包表記は、for文で処理した結果から新しいリストを作るための構文です。

  • 基本形は[作る値 for 要素 in 元の並び]
  • 条件で絞るなら最後にif 条件を付ける
  • 複雑な処理は通常のfor文の方が読みやすい
  • 元のリストを直接変えるのではなく、新しいリストを作る

リスト内包表記を読めるようになると、Pythonらしいリスト処理のコードがかなり追いやすくなります。

タイトルとURLをコピーしました