Python × 入門 | #20 リスト内包表記を使おう

0-19ではタプルとセットを学びました。今回はリストを作るときの便利な書き方「リスト内包表記」を学びます。

リスト内包表記

まずはPycoBlocksを開こう

下のPycoBlocksで直接作業するか、別タブで開き、生成されるPythonコードを見ながら進めてください。

パターン 書き方 意味
基本形[式 for 変数 in リスト]各要素に式を適用
条件付き[式 for 変数 in リスト if 条件]条件を満たすものだけ
変換付き[f(x) if 条件 else g(x) for x in list]条件で式を分岐
ネスト[式 for x in A for y in B]二重ループに相当

ステップ1:基本のリスト内包表記

for ループでリストを作るコードをより短く書ける構文です。PycoBlocks では py_list_comp ブロックを使います。まず普通の for ループと比較して理解しましょう。

リスト内包表記のブロック例
# 普通の for ループ
squares = []
for i in range(1, 6):
    squares.append(i ** 2)
print(squares)   # [1, 4, 9, 16, 25]

# リスト内包表記(同じ結果)
squares = [i ** 2 for i in range(1, 6)]
print(squares)   # [1, 4, 9, 16, 25]

# 文字列のリストを大文字に変換
words = ["apple", "banana", "cherry"]
upper = [w.upper() for w in words]
print(upper)     # ['APPLE', 'BANANA', 'CHERRY']

ステップ2:if 条件でフィルタリングする

末尾に if 条件 を加えると、条件を満たす要素だけを取り出せます。PycoBlocks では py_list_comp_if ブロックを使います。

if付きリスト内包表記のブロック例
# 偶数だけ取り出す
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = [n for n in nums if n % 2 == 0]
print(evens)     # [2, 4, 6, 8, 10]

# 5以上の要素を2倍にする
big_doubled = [n * 2 for n in nums if n >= 5]
print(big_doubled)   # [10, 12, 14, 16, 18, 20]

# 空文字を除去する
items = ["apple", "", "banana", "", "cherry"]
cleaned = [x for x in items if x != ""]
print(cleaned)   # ['apple', 'banana', 'cherry']

ステップ3:条件式で値を変換する

「条件を満たすものは A、そうでないものは B」という変換は、式1 if 条件 else 式2 を for の前に書きます。ブロックモードでは py_list_comp の式部分に py_ternary ブロックで条件式を入力します。

条件式でリストの値を変換するブロック例
nums = [1, -3, 5, -2, 8, -1]

# 負の数を 0 に変換する
clipped = [n if n >= 0 else 0 for n in nums]
print(clipped)   # [1, 0, 5, 0, 8, 0]

# 偶数は"偶"、奇数は"奇"に変換
labels = ["偶" if n % 2 == 0 else "奇" for n in range(1, 7)]
print(labels)    # ['奇', '偶', '奇', '偶', '奇', '偶']

ステップ4:辞書内包表記とセット内包表記

同じ考え方で辞書やセットも内包表記で作れます。辞書内包表記には py_dict_comp ブロック({キー: 値 for 変数 in リスト})、セット内包表記には py_set_comp ブロック({式 for 変数 in リスト})を使います。

辞書内包表記・セット内包表記のブロック例
# 辞書内包表記
words = ["apple", "banana", "cherry"]
lengths = {w: len(w) for w in words}
print(lengths)   # {'apple': 5, 'banana': 6, 'cherry': 6}

# セット内包表記(重複排除)
nums = [1, 2, 2, 3, 3, 3]
unique_squares = {n ** 2 for n in nums}
print(unique_squares)   # {1, 4, 9}

# 辞書を逆引きする
original = {"a": 1, "b": 2, "c": 3}
reversed_dict = {original[k]: k for k in original}
print(reversed_dict)   # {1: 'a', 2: 'b', 3: 'c'}

コーディングモードで書いてみよう

PycoBlocks には py_list_comppy_list_comp_ifpy_ternarypy_dict_comppy_set_comp ブロックがあります。入れ子ループなどより複雑なパターンは、コーディングモードで書けます。

# ピタゴラス数(a^2 + b^2 = c^2)を求める(c <= 20)
triples = [(a, b, c)
           for c in range(1, 21)
           for b in range(1, c)
           for a in range(1, b)
           if a**2 + b**2 == c**2]
print(triples)
# [(3, 4, 5), (6, 8, 10), (5, 12, 13), (8, 15, 17), (9, 12, 15)]

演習課題

課題20-1:1から20の3の倍数リスト

1から20までの整数のうち、3の倍数だけを集めたリストをリスト内包表記で作り、表示してみましょう。

▶ 模範解答と解説を見る

ブロックの組み合わせ例:

3の倍数リストを内包表記で作るブロック例
multiples_of_3 = [n for n in range(1, 21) if n % 3 == 0]
print(multiples_of_3)   # [3, 6, 9, 12, 15, 18]

解説: range(1, 21) で 1〜20 を生成し、% 3 == 0 で割り切れるものだけを選びます。

課題20-2:絶対値リスト

[-3, 1, -4, 1, 5, -9, 2, -6] の各要素を絶対値に変換したリストを内包表記で作ってみましょう。

▶ 模範解答と解説を見る

ブロックの組み合わせ例:

abs()で絶対値リストを作るブロック例
nums = [-3, 1, -4, 1, 5, -9, 2, -6]
abs_nums = [abs(n) for n in nums]
print(abs_nums)   # [3, 1, 4, 1, 5, 9, 2, 6]

解説: 組み込み関数 abs をリスト内包表記の中で使えます。

課題20-3:文字数が5文字以上の単語

["cat", "elephant", "ox", "giraffe", "ant", "hippopotamus"] から文字数が5文字以上の単語だけを取り出せ。

▶ 模範解答と解説を見る

ブロックの組み合わせ例:

長い名前をフィルタするブロック例
animals = ["cat", "elephant", "ox", "giraffe", "ant", "hippopotamus"]
long_names = [a for a in animals if len(a) >= 5]
print(long_names)   # ['elephant', 'giraffe', 'hippopotamus']

解説: len(a) >= 5 を条件にすると5文字以上の要素だけが残ります。

課題20-4:FizzBuzzリスト

1から15の整数に対して、3の倍数なら "Fizz"、5の倍数なら "Buzz"、両方の倍数なら "FizzBuzz"、それ以外は数字そのままのリストを内包表記で作ってみましょう。

▶ 模範解答と解説を見る

ブロックの組み合わせ例:

FizzBuzzを内包表記で作るブロック例
result = [
    "FizzBuzz" if n % 15 == 0
    else "Fizz" if n % 3 == 0
    else "Buzz" if n % 5 == 0
    else n
    for n in range(1, 16)
]
print(result)

解説: 三項演算子(条件式)を入れ子にすることで複数条件に対応できます。15の倍数を最初に判定することがポイントです。

課題20-5:単語と文字数の辞書

["Python", "Java", "C", "Ruby", "Go"] から、各単語をキー、文字数を値とする辞書を辞書内包表記で作ってみましょう。

▶ 模範解答と解説を見る

ブロックの組み合わせ例:

辞書内包表記で言語名と文字数を対応付けるブロック例
langs = ["Python", "Java", "C", "Ruby", "Go"]
length_dict = {lang: len(lang) for lang in langs}
print(length_dict)
# {'Python': 6, 'Java': 4, 'C': 1, 'Ruby': 4, 'Go': 2}

解説: 辞書内包表記は {キー: 値 for 変数 in イテラブル} の形で書きます。

まとめ

  • [式 for 変数 in リスト] の形でリストを一行で作れます
  • if 条件 を末尾に加えるとフィルタリングできます
  • 式1 if 条件 else 式2 を for の前に置くと値を変換できます
  • 辞書内包表記 {k: v for ...}、セット内包表記 {式 for ...} も使えます
  • for ループより短く書けますが、複雑になりすぎたら素直にループを使いましょう

次は「便利な組み込み関数」を学びます。→ Python × 入門 | #21 便利な組み込み関数

PAGE TOP