採点されません。匿名です。 間違えることは学習の一部です。読むだけでもかまいません。

L03 ch03 — 内包表記 (comprehension)

テクノロジ系 / L04 loop — ループ

L03 ch03 — 内包表記 (comprehension)

「for + append」を 1 行に圧縮する Python の定番テクニック

ゴール

  • リスト内包表記の構文を書ける
  • if フィルタ付き内包表記を書ける
  • 辞書内包表記 / 集合内包表記を書ける
  • 「使うべき場面」と「使うと読みづらい場面」の境界を判断できる

なぜ内包表記なのか

for + append の冗長さを排除し、「何を作るか」を 1 行で示す。

# ❌ 冗長
squares = []
for x in range(5):
    squares.append(x * x)

# ✅ 内包表記
squares = [x * x for x in range(5)]
# → [0, 1, 4, 9, 16]

基本構文

[ <式> for <変数> in <イテラブル> ]
nums = [1, 2, 3, 4]

doubled = [n * 2 for n in nums]
# → [2, 4, 6, 8]

names = ["taro", "jiro"]
upper = [n.upper() for n in names]
# → ["TARO", "JIRO"]

if フィルタ

[ <式> for <変数> in <イテラブル> if <条件> ]
nums = [1, 2, 3, 4, 5, 6]

evens = [n for n in nums if n % 2 == 0]
# → [2, 4, 6]

squares_of_odd = [n * n for n in nums if n % 2 == 1]
# → [1, 9, 25]

if-else は「式」の位置に書く

if の位置で意味が変わる。

nums = [1, 2, 3, 4]

# フィルタ (条件を満たすものだけ残す)
[n for n in nums if n % 2 == 0]
# → [2, 4]

# 三項演算 (全部残すが値を分岐)
["even" if n % 2 == 0 else "odd" for n in nums]
# → ["odd", "even", "odd", "even"]

辞書内包表記

names = ["taro", "jiro", "saburo"]

# index → name の辞書
name_map = {i: n for i, n in enumerate(names)}
# → {0: "taro", 1: "jiro", 2: "saburo"}

# 文字列長の辞書
lengths = {n: len(n) for n in names}
# → {"taro": 4, "jiro": 4, "saburo": 6}

集合内包表記

words = ["apple", "banana", "apple", "cherry", "banana"]

unique_lengths = {len(w) for w in words}
# → {5, 6}   (重複は自動排除)

{} でも辞書か集合かは中身で判別される (k: v なら dict、単独値なら set)。

ネスト (二重ループ)

pairs = [(x, y) for x in [1, 2] for y in [10, 20]]
# → [(1, 10), (1, 20), (2, 10), (2, 20)]

# 行列の flatten
matrix = [[1, 2, 3], [4, 5, 6]]
flat = [v for row in matrix for v in row]
# → [1, 2, 3, 4, 5, 6]

外側 for を先に書く (通常の for ネストと同じ順)。

ジェネレータ式

[]() にすると遅延評価のジェネレータになる。

# リスト (全要素をメモリに展開)
total = sum([n * n for n in range(1_000_000)])

# ジェネレータ (1 要素ずつ評価 = 省メモリ)
total = sum(n * n for n in range(1_000_000))

sum / any / all / max に渡すときは () 推奨。

drill

drill/01-fill-listcomp/ — 偶数のみを 2 倍にして返すリスト内包表記を完成させる

使うべきでない場面

内包表記は「1 行で意図が読める」前提の道具。複雑になったら for に戻す。

# ❌ 読みづらい (条件 + 三項 + ネスト)
result = [
    f(x) if x > 0 else g(x)
    for row in data
    for x in row
    if x is not None and x != 0
]

# ✅ for ループに分解
result = []
for row in data:
    for x in row:
        if x is None or x == 0:
            continue
        result.append(f(x) if x > 0 else g(x))

よくある詰まり

症状原因対処
SyntaxErrorif が通らないif-elsefor の後に書いた三項なら式の位置 [a if c else b for ...]
辞書のつもりが set になる{x for x in xs} と書いた{k: v for ...} の形にする
巨大データで MemoryErrorリストで全展開した() のジェネレータ式に変える

次に学ぶ領域

領域続けて読む
ジェネレータ関数 (yield)function/ 後続 chapter
map / filter との比較関数型スタイル chapter
itertools標準ライブラリ chapter
力試ししたい方は クイズ形式の演習(任意) もあります。読むだけでも十分です。