メインコンテンツへスキップ
Lesson6 / 8

リスト内包表記

目次

このレッスンで学ぶこと

  • リスト内包表記とは何か
  • 基本的な構文
  • 条件付きリスト内包表記
  • 実用的な使い方

リスト内包表記とは

リスト内包表記は、for文を使ったリスト作成をPythonらしい簡潔な表記法で書く方法です。新しいリストを1行で作成でき、データの変換やフィルタリングに非常に便利です。

形式説明
[式 for 変数 in イテラブル]基本形(変換)[x*2 for x in range(5)]
[式 for 変数 in イテラブル if 条件]条件付き(フィルタ)[x for x in range(10) if x % 2 == 0]
[式1 if 条件 else 式2 for 変数 in イテラブル]if-else(分岐)[x*2 if x % 2 == 0 else x for x in range(5)]

主な特徴:

  • for文と比較して非常に簡潔に書ける
  • 新しいリストを作成する(元のリストは変更されない)
  • 変換、フィルタリング、条件分岐が全て内包表記で実現可能
  • 複雑すぎる場合は通常のfor文を使う方が読みやすい

簡単なコード例:

Python
# 変換:1から5の2乗
squares = [x**2 for x in range(1, 6)]
print(f"平方数: {squares}")

# フィルタ:偶数のみ
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = [x for x in numbers if x % 2 == 0]
print(f"偶数: {evens}")

# if-else:偶数は2倍、奇数はそのまま
result = [x*2 if x % 2 == 0 else x for x in range(1, 6)]
print(f"変換: {result}")

実行結果:

平方数: [1, 4, 9, 16, 25]
偶数: [2, 4, 6, 8, 10]
変換: [1, 4, 3, 8, 5]

なぜリスト内包表記が必要なのか?

新しいリストを作成するとき、リスト内包表記を使うと簡潔に書けます。

Python
# 通常のfor文
squares = []
for i in range(1, 6):
    squares.append(i ** 2)
print(squares)

# リスト内包表記
squares = [i ** 2 for i in range(1, 6)]
print(squares)

実行結果:

[1, 4, 9, 16, 25]
[1, 4, 9, 16, 25]

リスト内包表記を使うことで、コードを1行で簡潔に書けます。

💡 豆知識: リスト内包表記は「List Comprehension」と呼ばれ、Pythonの特徴的な機能の一つです。数学の集合の記法に似た構文で、読みやすく効率的なコードが書けます。


リスト内包表記の基本

基本構文

機能: for文を使って新しいリストを1行で作成します。

書き方:

Python
[for 変数 in イテラブル]

用途: リストの変換、フィルタリング、数値の生成

注意点:

  • 新しいリストが作られる
  • 複雑すぎると読みにくくなる
  • 通常のfor文の代わりになる
Python
# 1から5までの数値のリスト
numbers = [i for i in range(1, 6)]
print(numbers)

# 1から5までの2倍のリスト
doubled = [i * 2 for i in range(1, 6)]
print(doubled)

# 文字列のリスト
fruits = ["apple", "banana", "orange"]
upper = [fruit.upper() for fruit in fruits]
print(upper)

実行結果:

[1, 2, 3, 4, 5]
[2, 4, 6, 8, 10]
['APPLE', 'BANANA', 'ORANGE']

様々な変換

数値の変換

Python
# 平方数
squares = [x ** 2 for x in range(1, 11)]
print(f"平方数: {squares}")

# 立方数
cubes = [x ** 3 for x in range(1, 6)]
print(f"立方数: {cubes}")

# 計算式
values = [x * 2 + 1 for x in range(5)]
print(f"計算式: {values}")

実行結果:

平方数: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
立方数: [1, 8, 27, 64, 125]
計算式: [1, 3, 5, 7, 9]

文字列の変換

Python
words = ["hello", "world", "python"]

# 大文字に変換
upper_words = [word.upper() for word in words]
print(f"大文字: {upper_words}")

# 文字数のリスト
lengths = [len(word) for word in words]
print(f"文字数: {lengths}")

# 最初の文字
first_chars = [word[0] for word in words]
print(f"最初の文字: {first_chars}")

実行結果:

大文字: ['HELLO', 'WORLD', 'PYTHON']
文字数: [5, 5, 6]
最初の文字: ['h', 'w', 'p']

条件付きリスト内包表記

if文を使ったフィルタ

機能: 条件に合う要素だけを含む新しいリストを作成します。

書き方:

Python
[for 変数 in イテラブル if 条件]

用途: データのフィルタリング、条件に合う要素の抽出

注意点:

  • ifは末尾に書く
  • 複数条件も可能
  • elseを使う場合は構文が異なる
Python
# 偶数だけ
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even = [x for x in numbers if x % 2 == 0]
print(f"偶数: {even}")

# 5より大きい数
greater_than_5 = [x for x in numbers if x > 5]
print(f"5より大きい: {greater_than_5}")

# 3の倍数
multiples_of_3 = [x for x in numbers if x % 3 == 0]
print(f"3の倍数: {multiples_of_3}")

実行結果:

偶数: [2, 4, 6, 8, 10]
5より大きい: [6, 7, 8, 9, 10]
3の倍数: [3, 6, 9]

if-else を使った変換

機能: 条件によって異なる値を設定します。

書き方:

Python
[1 if 条件 else2 for 変数 in イテラブル]

用途: 条件による値の切り替え、データの正規化

注意点:

  • if-elseは式の前に書く
  • フィルタとは構文が異なる
Python
# 偶数は2倍、奇数はそのまま
numbers = [1, 2, 3, 4, 5]
result = [x * 2 if x % 2 == 0 else x for x in numbers]
print(f"結果: {result}")

# 正負の判定
values = [-2, -1, 0, 1, 2]
signs = ["負" if x < 0 else "正" if x > 0 else "ゼロ" for x in values]
print(f"符号: {signs}")

実行結果:

結果: [1, 4, 3, 8, 5]
符号: ['負', '負', 'ゼロ', '正', '正']

複雑な例

ネストしたループ

Python
# 2次元の組み合わせ
pairs = [(x, y) for x in range(3) for y in range(3)]
print(f"組み合わせ: {pairs}")

# 掛け算の結果
products = [x * y for x in range(1, 4) for y in range(1, 4)]
print(f"積: {products}")

# 条件付き組み合わせ
filtered_pairs = [(x, y) for x in range(5) for y in range(5) if x < y]
print(f"x < y: {filtered_pairs}")

実行結果:

組み合わせ: [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
積: [1, 2, 3, 2, 4, 6, 3, 6, 9]
x < y: [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]

文字列の処理

Python
# 文字列を文字のリストに
text = "Python"
chars = [c for c in text]
print(f"文字: {chars}")

# 大文字だけ抽出
mixed = "HeLLo WoRLd"
uppercase = [c for c in mixed if c.isupper()]
print(f"大文字: {uppercase}")

# 母音を抽出
text = "hello world"
vowels = [c for c in text if c in "aeiou"]
print(f"母音: {vowels}")

実行結果:

文字: ['P', 'y', 't', 'h', 'o', 'n']
大文字: ['H', 'L', 'L', 'W', 'R', 'L']
母音: ['e', 'o', 'o']

具体例

例1: 価格計算

Python
# 価格リスト(税抜)
prices = [100, 250, 500, 1000, 1500]

# 税込価格(10%)
prices_with_tax = [int(price * 1.1) for price in prices]
print(f"税抜: {prices}")
print(f"税込: {prices_with_tax}")

# 1000円以上の商品
expensive = [price for price in prices if price >= 1000]
print(f"1000円以上: {expensive}")

実行結果:

税抜: [100, 250, 500, 1000, 1500]
税込: [110, 275, 550, 1100, 1650]
1000円以上: [1000, 1500]

例2: 成績処理

Python
# 点数リスト
scores = [85, 92, 45, 78, 95, 60, 88, 55, 90]

# 合格者(60点以上)
passed = [score for score in scores if score >= 60]
print(f"合格: {passed}")

# 不合格者
failed = [score for score in scores if score < 60]
print(f"不合格: {failed}")

# 評価(80以上: 優、60以上: 良、それ以外: 可)
grades = ["優" if s >= 80 else "良" if s >= 60 else "可" for s in scores]
print(f"評価: {grades}")

実行結果:

合格: [85, 92, 78, 95, 60, 88, 90]
不合格: [45, 55]
評価: ['優', '優', '可', '良', '優', '良', '優', '可', '優']

例3: データの整形

Python
# 名前リスト(空白あり)
names = ["  Alice  ", "Bob", "  Charlie  ", "David"]

# 空白を削除
cleaned = [name.strip() for name in names]
print(f"整形後: {cleaned}")

# 大文字に変換
upper_names = [name.strip().upper() for name in names]
print(f"大文字: {upper_names}")

# 5文字以上の名前
long_names = [name.strip() for name in names if len(name.strip()) >= 5]
print(f"5文字以上: {long_names}")

実行結果:

整形後: ['Alice', 'Bob', 'Charlie', 'David']
大文字: ['ALICE', 'BOB', 'CHARLIE', 'DAVID']
5文字以上: ['Alice', 'Charlie', 'David']

例4: 座標の生成

Python
# 格子点(0〜4の範囲)
grid = [(x, y) for x in range(5) for y in range(5)]
print(f"格子点数: {len(grid)}")
print(f"最初の10個: {grid[:10]}")

# 対角線上の点(x == y)
diagonal = [(x, y) for x in range(5) for y in range(5) if x == y]
print(f"対角線: {diagonal}")

# マンハッタン距離が2以下の点
close_points = [(x, y) for x in range(-2, 3) for y in range(-2, 3) if abs(x) + abs(y) <= 2]
print(f"近い点: {close_points}")

実行結果:

格子点数: 25
最初の10個: [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4)]
対角線: [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
近い点: [(-2, 0), (-1, -1), (-1, 0), (-1, 1), (0, -2), (0, -1), (0, 0), (0, 1), (0, 2), (1, -1), (1, 0), (1, 1), (2, 0)]

例5: FizzBuzz

Python
# FizzBuzzをリスト内包表記で
fizzbuzz = [
    "FizzBuzz" if i % 15 == 0 else
    "Fizz" if i % 3 == 0 else
    "Buzz" if i % 5 == 0 else
    str(i)
    for i in range(1, 31)
]

print("FizzBuzz:")
for i, value in enumerate(fizzbuzz, 1):
    print(f"{i:2}: {value}")

実行結果:

FizzBuzz:
 1: 1
 2: 2
 3: Fizz
 4: 4
 5: Buzz
...
15: FizzBuzz
...

例6: データの変換

Python
# 温度データ(摂氏)
celsius = [0, 10, 20, 30, 40]

# 華氏に変換
fahrenheit = [c * 9/5 + 32 for c in celsius]

print("=== 温度変換 ===")
for c, f in zip(celsius, fahrenheit):
    print(f"{c}°C = {f}°F")

実行結果:

=== 温度変換 ===
0°C = 32.0°F
10°C = 50.0°F
20°C = 68.0°F
30°C = 86.0°F
40°C = 104.0°F

通常のfor文との使い分け

リスト内包表記を使うべき場合

Python
# 簡単な変換 → リスト内包表記が適切
squares = [x ** 2 for x in range(10)]

# 条件付きフィルタ → リスト内包表記が適切
evens = [x for x in range(20) if x % 2 == 0]

通常のfor文を使うべき場合

Python
# 複雑な処理 → 通常のfor文が適切
results = []
for x in range(10):
    # 複数行の処理
    value = x ** 2
    if value > 50:
        value = 50
    results.append(value)

# 副作用がある処理 → 通常のfor文が適切
for item in items:
    print(item)  # 出力など
    process(item)  # 外部関数の呼び出し

よくある間違い

間違い1: 括弧を忘れる

Python
# 間違い: 括弧がない
# squares = x ** 2 for x in range(5)  # エラー

# 正しい
squares = [x ** 2 for x in range(5)]
print(squares)

実行結果:

[0, 1, 4, 9, 16]

間違い2: if-elseの位置

Python
# 間違い: if-elseが末尾
# result = [x for x in range(10) if x % 2 == 0 else x * 2]  # エラー

# 正しい: if-elseは式の前
result = [x if x % 2 == 0 else x * 2 for x in range(10)]
print(result)

# フィルタだけならif は末尾
filtered = [x for x in range(10) if x % 2 == 0]
print(filtered)

実行結果:

[0, 2, 2, 6, 4, 10, 6, 14, 8, 18]
[0, 2, 4, 6, 8]

間違い3: 複雑すぎる内包表記

Python
# 読みにくい例
result = [[x*y for y in range(5) if y % 2 == 0] for x in range(5) if x % 2 != 0]

# 読みやすく分割
odds = [x for x in range(5) if x % 2 != 0]
result = []
for x in odds:
    row = [x*y for y in range(5) if y % 2 == 0]
    result.append(row)

print(result)

実行結果:

[[0, 2, 4], [0, 6, 12]]

間違い4: 副作用のある内包表記

Python
# 良くない例: 副作用がある
# [print(x) for x in range(5)]  # 動くが推奨されない

# 正しい: 通常のfor文を使う
for x in range(5):
    print(x)

間違い5: 変数のスコープ

Python
# Python 3では内包表記の変数は外に漏れない
[x for x in range(5)]

try:
    print(x)  # NameError
except NameError:
    print("xは内包表記の外では使えません")

# 通常のfor文は変数が残る
for y in range(5):
    pass
print(f"yは使えます: {y}")

実行結果:

xは内包表記の外では使えません
yは使えます: 4

練習問題

問題1(基礎)⭐☆☆

1から10までの数値の2乗のリストを作成してください。

💡 ヒント

[x ** 2 for x in range(...)] の形を使います。

✅ 解答例
Python
squares = [x ** 2 for x in range(1, 11)]
print(squares)

実行結果:

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

問題2(基礎)⭐☆☆

リスト [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] から偶数だけを抽出してください。

💡 ヒント

if文で偶数判定します。

✅ 解答例
Python
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = [x for x in numbers if x % 2 == 0]
print(evens)

実行結果:

[2, 4, 6, 8, 10]

問題3(応用)⭐⭐☆

文字列のリスト ["apple", "banana", "orange"] を大文字に変換したリストを作成してください。

💡 ヒント

upper()メソッドを使います。

✅ 解答例
Python
fruits = ["apple", "banana", "orange"]
upper_fruits = [fruit.upper() for fruit in fruits]
print(upper_fruits)

実行結果:

['APPLE', 'BANANA', 'ORANGE']

まとめ

このレッスンでは、リスト内包表記で簡潔にリストを生成する方法を学びました。

  • ループと条件を1行で表現し、短く読みやすいコードを書けます。
  • 既存リストから変換・抽出した新しいリストを効率的に作れます。
  • 通常のfor文との対応関係を理解して使い分けられます。
  • 条件が複雑な場合は可読性を優先して通常のfor文を選ぶ判断が重要です。
  • まず正しいfor文を書いてから内包表記へ変換すると安全です。