Pythonのリスト内包表記とifを徹底解説!条件付きフィルタリング&応用テクニック

目次

1. はじめに

Pythonの「リスト内包表記(List Comprehension)」は、リストを簡潔に作成するための便利な構文です。通常のforループを使ってリストを生成する場合に比べ、コードの可読性と実行速度の両面でメリットがあります。

特に、リスト内包表記にif文を組み合わせると、条件を満たす要素のみを抽出できるため、より柔軟なリスト操作が可能になります。本記事では、Pythonのリスト内包表記とifを組み合わせる方法を基本から応用まで詳しく解説していきます。

リスト内包表記とは?

リスト内包表記とは、Pythonのリストを簡潔に作成するための構文です。通常のforループを使うよりも短いコードで、可読性の高いプログラムを書くことができます。

例えば、0から4までの整数のリストを作成する場合、通常のforループを使うと以下のようになります。

numbers = []
for i in range(5):
    numbers.append(i)
print(numbers)  # [0, 1, 2, 3, 4]

しかし、リスト内包表記を使うと、これを1行で書くことができます。

numbers = [i for i in range(5)]
print(numbers)  # [0, 1, 2, 3, 4]

リスト内包表記を使うメリット

リスト内包表記を活用することで、以下のメリットがあります。

  1. コードが短くなり、可読性が向上する
  • 通常のforループと比べて、コードの行数を減らすことができるため、スッキリとしたコードを書くことができます。
  1. 処理速度が向上する
  • forループよりもリスト内包表記の方がPythonの内部最適化が働くため、処理が高速になることが多いです。
  1. リストのフィルタリングが簡単にできる
  • if文を組み合わせることで、特定の条件に一致する要素のみを抽出できます。

なぜリスト内包表記にifを使うのか?

リスト内包表記にifを組み合わせると、リストの要素を動的にフィルタリングできます。例えば、0から9の整数のうち、偶数だけをリストに格納する場合、forループを使うと次のようになります。

evens = []
for i in range(10):
    if i % 2 == 0:
        evens.append(i)
print(evens)  # [0, 2, 4, 6, 8]

しかし、リスト内包表記を使うと、たった1行でこの処理を実装できます。

evens = [i for i in range(10) if i % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

このように、リスト内包表記にifを組み合わせることで、条件を満たす要素のみをリストに追加する処理が簡単に書けるようになります。

この記事で学べること

本記事では、Pythonのリスト内包表記とif文の組み合わせについて、以下の内容を詳しく解説します。

  • リスト内包表記の基本構文
  • ifを使った条件付きリスト内包表記
  • if-elseを使ったリスト内包表記
  • ネストしたリスト内包表記の活用方法
  • リスト内包表記を使う際の注意点とベストプラクティス
  • よくある質問(FAQ)

リスト内包表記を活用することで、Pythonのコードをよりシンプルかつ効率的に書くことができます。これから詳しく解説していくので、ぜひ最後まで読んで、実際にコードを書きながら理解を深めてください!

2. Pythonのリスト内包表記の基本

前のセクションでは、リスト内包表記がどのようなものか、そのメリットについて紹介しました。ここからは、リスト内包表記の基本構文を詳しく解説し、具体的な例を通して理解を深めていきます。

リスト内包表記の基本構文

リスト内包表記の基本的な構文は以下のようになります。

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

構文の要素

  • : 変数に対して適用する処理(計算や関数など)
  • for 変数 in イテラブル: イテラブル(リスト、タプル、レンジなど)から各要素を取り出すループ

例えば、0から4までの整数を含むリストを作成する場合、通常のforループを使うと以下のようになります。

numbers = []
for i in range(5):
    numbers.append(i)
print(numbers)  # [0, 1, 2, 3, 4]

しかし、リスト内包表記を使うと、これを1行で書くことができます。

numbers = [i for i in range(5)]
print(numbers)  # [0, 1, 2, 3, 4]

リスト内包表記の基本例

リスト内包表記を使うことで、リストの作成や変換が簡単になります。ここでは、基本的な例をいくつか紹介します。

1. 各要素を2乗する

リスト内包表記を使用して、0から9までの数値の2乗をリストに格納する例です。

squares = [i**2 for i in range(10)]
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

通常のforループで書く場合と比較すると、コードが大幅に短縮されることがわかります。

squares = []
for i in range(10):
    squares.append(i**2)
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

2. 文字列のリストを加工

文字列のリストをすべて大文字に変換する例です。

words = ["python", "list", "comprehension"]
uppercase_words = [word.upper() for word in words]
print(uppercase_words)  # ['PYTHON', 'LIST', 'COMPREHENSION']

同じ処理をforループで書く場合は以下のようになります。

words = ["python", "list", "comprehension"]
uppercase_words = []
for word in words:
    uppercase_words.append(word.upper())
print(uppercase_words)  # ['PYTHON', 'LIST', 'COMPREHENSION']

リスト内包表記を使うことで、データ変換の処理をシンプルに記述できます。

3. リストを平坦化(ネストされたリストの要素を抽出)

ネストされたリスト(2次元リスト)を1次元のリストに変換する場合にもリスト内包表記は便利です。

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

通常のforループで書くと、次のようにネストしたループが必要になります。

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = []
for row in matrix:
    for num in row:
        flattened.append(num)
print(flattened)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

リスト内包表記を使うことで、ループのネストをシンプルに記述できることが分かります。

リスト内包表記と通常のforループの比較

項目リスト内包表記通常のforループ
コードの短さ短い(1行で記述可能)長い(複数行のコードが必要)
可読性シンプルで直感的(簡単な処理なら分かりやすい)長くなると見やすいが、冗長になりがち
実行速度高速(Pythonの内部最適化が働く)やや遅い(明示的なループ処理のため)
可読性の限界ネストが深くなると読みにくくなるネストが深くても整理しやすい

基本的に、簡単な処理はリスト内包表記、複雑な処理は通常のforループを使うのがベスト です。

まとめ

  • リスト内包表記は、簡潔な構文でリストを作成できる便利な機能
  • 基本構文は [式 for 変数 in イテラブル]
  • 数値計算、文字列変換、リストの平坦化など、さまざまな用途で使える
  • 通常のforループよりもコードが短くなり、処理速度も向上する
  • ただし、ネストが深くなると可読性が下がるので注意

3. ifを使った条件付きリスト内包表記

前のセクションでは、リスト内包表記の基本について学びました。ここからは、リスト内包表記にifを組み合わせて、条件付きのリストを作成する方法を解説します。

リスト内包表記にifを加えることで、リストのフィルタリングが容易になり、特定の条件を満たす要素だけをリストに追加することができます。

ifを使ったリスト内包表記の基本構文

条件を指定してリストを作成する場合、基本構文は以下のようになります。

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

構文の要素

  • : 各要素に適用する処理
  • for 変数 in イテラブル: イテラブル(リスト、タプル、レンジなど)をループ
  • if 条件: if文を使って特定の条件を満たす場合のみリストに追加

基本的な使用例

1. 偶数のみを抽出

例えば、0から9の整数のうち、偶数だけをリストに格納する場合、通常のforループを使うと以下のようになります。

evens = []
for i in range(10):
    if i % 2 == 0:
        evens.append(i)
print(evens)  # [0, 2, 4, 6, 8]

リスト内包表記を使うと、以下のように簡潔に書けます。

evens = [i for i in range(10) if i % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

if文をリスト内包表記に組み込むことで、余分なappend()を省略でき、コードが短くなります。

2. 文字列リストのフィルタリング

リスト内包表記を使うと、文字列のリストから特定の条件を満たす要素だけを抽出することもできます。

例えば、「python」「java」「c++」「ruby」の中から、5文字以上のプログラミング言語だけをリストに格納する場合、以下のように記述します。

languages = ["python", "java", "c++", "ruby"]
long_languages = [lang for lang in languages if len(lang) >= 5]
print(long_languages)  # ['python']

3. 特定の文字を含む単語を抽出

リスト内包表記を使って、特定の文字を含む単語だけを抽出することもできます。

例えば、"a" を含む単語だけを抽出する場合は次のように書けます。

words = ["apple", "banana", "cherry", "date"]
words_with_a = [word for word in words if "a" in word]
print(words_with_a)  # ['apple', 'banana', 'date']

条件を複数指定する方法

if文の条件を複数指定する場合、andor を使うことができます。

1. 偶数かつ3の倍数のみを抽出

filtered_numbers = [i for i in range(20) if i % 2 == 0 and i % 3 == 0]
print(filtered_numbers)  # [0, 6, 12, 18]

2. 複数の条件を満たす文字列を抽出

words = ["python", "java", "c++", "ruby", "go", "haskell"]
filtered_words = [word for word in words if len(word) >= 5 and "o" in word]
print(filtered_words)  # ['python']

頻出エラーと対策

1. ifの位置を間違える

間違った例(ifの位置が不適切)

numbers = [if i % 2 == 0 for i in range(10)]

エラー: SyntaxError: invalid syntax

正しい例

numbers = [i for i in range(10) if i % 2 == 0]

2. and / or の使い方を間違える

間違った例

words = ["apple", "banana", "cherry"]
filtered_words = [word for word in words if len(word) > 5 or "a" in word]

期待する結果を得るためには and を使用

filtered_words = [word for word in words if len(word) > 5 and "a" in word]

まとめ

  • リスト内包表記にifを追加すると、条件を満たす要素のみをリストに格納できる
  • 構文は [式 for 変数 in イテラブル if 条件]
  • 偶数の抽出、文字列のフィルタリングなど、さまざまな用途で使える
  • 条件を複数指定する場合は and / or を活用
  • ifの位置や条件の書き方を間違えるとエラーになるので注意

4. if-elseを使ったリスト内包表記

前のセクションでは、ifを使ってリストの要素をフィルタリングする方法を学びました。しかし、条件によって異なる値をリストに格納したい場合は、if-elseを組み合わせる必要があります。

このセクションでは、if-elseを使ったリスト内包表記の書き方と、実用的な例を詳しく解説します。

if-elseを使ったリスト内包表記の基本構文

リスト内包表記にif-elseを組み込む場合の構文は以下のようになります。

[式1 if 条件 else 式2 for 変数 in イテラブル]

構文の要素

  • 式1: 条件を満たす場合に適用される値や処理
  • 条件: ifで指定する条件
  • else 式2: 条件を満たさない場合に適用される値や処理
  • for 変数 in イテラブル: イテラブル(リスト、レンジなど)をループ処理

if-elseを使う場合は、ifforの前に来ることに注意!
ifのみの場合は forの後に書きますが、if-elseを使う場合は forの前に書きます。

基本的な使用例

1. 偶数はそのまま、奇数は”odd”に変換

例えば、0から9までの整数のうち、偶数はそのままリストに格納し、奇数は”odd”に変換 する場合、通常のforループでは次のようになります。

numbers = []
for i in range(10):
    if i % 2 == 0:
        numbers.append(i)
    else:
        numbers.append("odd")

print(numbers)  
# [0, 'odd', 2, 'odd', 4, 'odd', 6, 'odd', 8, 'odd']

リスト内包表記を使うと、これを1行で書くことができます。

numbers = [i if i % 2 == 0 else "odd" for i in range(10)]
print(numbers)  
# [0, 'odd', 2, 'odd', 4, 'odd', 6, 'odd', 8, 'odd']

ifelseを使うことで、リストの値を柔軟に変換できることがわかります。

2. 0以下の値を”negative”に変換

例えば、リスト内の数値が0以下の場合は "negative" に変換し、それ以外の数値はそのまま保持する処理を考えます。

numbers = [-5, 3, 0, 8, -2, 7]
modified_numbers = [num if num > 0 else "negative" for num in numbers]
print(modified_numbers)  
# ['negative', 3, 'negative', 8, 'negative', 7]

3. 数値を正負で分類

例えば、リスト内の整数を “positive”(正の数)と “negative”(負の数)に分類 する場合、以下のように書けます。

numbers = [-10, 15, 0, -5, 20]
categories = ["positive" if num > 0 else "negative" for num in numbers]
print(categories)  
# ['negative', 'positive', 'negative', 'negative', 'positive']

リスト内包表記でif-elseを使う際の注意点

1. ifの位置を間違えない

間違った例(エラーになる)

numbers = [i for i in range(10) if i % 2 == 0 else "odd"]

エラー: SyntaxError: invalid syntax

正しい書き方

numbers = [i if i % 2 == 0 else "odd" for i in range(10)]

👉 if-elseを使う場合はforの前に記述する必要がある!

2. if-elseifの違い

  • ifのみの場合(要素のフィルタリング)
  evens = [i for i in range(10) if i % 2 == 0]
  print(evens)  # [0, 2, 4, 6, 8]

ifのみの場合、条件を満たさない要素はリストに含まれません。

  • if-elseを使う場合(値を変換)
  numbers = [i if i % 2 == 0 else "odd" for i in range(10)]
  print(numbers)  # [0, 'odd', 2, 'odd', 4, 'odd', 6, 'odd', 8, 'odd']

if-elseを使うと、すべての要素がリストに含まれ、条件に応じて変換されます。

まとめ

  • if-elseを使うと、条件によって異なる値をリストに格納できる
  • if-elseを使う場合はforの前に記述する
  • ifのみのリスト内包表記とは異なり、すべての要素をリストに含めつつ変換できる
  • 数値・文字列の分類や、特定の条件で値を変更するのに便利
  • ネストしたif-elseを使うと、複数の条件を組み合わせることも可能
RUNTEQ(ランテック)|超実戦型エンジニア育成スクール

5. ネストしたリスト内包表記と条件分岐

前のセクションでは、if-elseを使ったリスト内包表記について学びました。このセクションでは、ネストしたリスト内包表記(多重ループを含むリスト内包表記) の使い方を解説します。

リスト内包表記では、通常のforループと同じように 多重ループ(ネスト) を使うことができます。これにより、リストのリスト(2次元リストなど)を効果的に処理することが可能になります。

ネストしたリスト内包表記の基本構文

リスト内包表記でループをネストさせる場合の基本構文は以下のようになります。

[式 for 変数1 in イテラブル1 for 変数2 in イテラブル2]

構文の要素

  • : 変数に適用する処理
  • for 変数1 in イテラブル1: 最初のループ
  • for 変数2 in イテラブル2: 内側のループ(ネストされたループ)

通常のforループと同じように 左側から順にループが回る というのがポイントです。

基本的な使用例

1. 2次元リストのフラット化(平坦化)

例えば、2次元リスト(リストのリスト)を1次元のリストに変換する場合、通常のforループでは次のようになります。

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = []
for row in matrix:
    for num in row:
        flattened.append(num)
print(flattened)  
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

リスト内包表記を使うと、次のように 1行で記述 できます。

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened)  
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

→ ループのネストをリスト内包表記に適用すると、より 短く直感的なコード を書くことができます。

2. すべての組み合わせを作成

例えば、A, B, C1, 2, 3 のすべての組み合わせを作成する場合、通常のforループでは次のようになります。

letters = ["A", "B", "C"]
numbers = [1, 2, 3]
combinations = []

for letter in letters:
    for number in numbers:
        combinations.append(f"{letter}{number}")

print(combinations)  
# ['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']

リスト内包表記を使うと、次のように 簡潔に記述 できます。

letters = ["A", "B", "C"]
numbers = [1, 2, 3]
combinations = [f"{letter}{number}" for letter in letters for number in numbers]

print(combinations)  
# ['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']

多重ループを1行で記述できるのが、ネストしたリスト内包表記の強み です。

条件分岐を組み合わせる

ネストしたリスト内包表記でも、ifif-elseを使って条件分岐を組み込むことができます。

3. 偶数のペアのみを取得

例えば、1~34~6 の組み合わせのうち、 和が偶数になるペアのみ を取得したい場合、通常のforループでは次のようになります。

list1 = [1, 2, 3]
list2 = [4, 5, 6]
pairs = []

for x in list1:
    for y in list2:
        if (x + y) % 2 == 0:
            pairs.append((x, y))

print(pairs)  
# [(1, 5), (2, 4), (2, 6), (3, 5)]

リスト内包表記を使うと、 短く、直感的に書ける ようになります。

list1 = [1, 2, 3]
list2 = [4, 5, 6]
pairs = [(x, y) for x in list1 for y in list2 if (x + y) % 2 == 0]

print(pairs)  
# [(1, 5), (2, 4), (2, 6), (3, 5)]

ネストしたリスト内包表記を使う際の注意点

1. 可読性が低下しやすい

  • ネストが深くなると可読性が下がるため、過度な使用は避ける
  • 可読性を優先する場合は通常のforループを使う

2. ifの位置に注意

  • ifのみを使う場合 → forの後
  • if-elseを使う場合 → forの前

3. ネストが複雑になりすぎる場合は関数化

  • ネストが深くなり、可読性が落ちる場合は、リスト内包表記を使わず、関数で分けるのも一つの方法。

まとめ

  • ネストしたリスト内包表記を使うと、2次元リストの処理や多重ループを簡潔に記述できる
  • ifを組み合わせることで、条件を満たす要素のみを抽出可能
  • if-elseを組み合わせると、要素ごとに異なる値を設定できる
  • ただし、ネストが深くなりすぎると可読性が低下するため注意

6. リスト内包表記のベストプラクティスと注意点

リスト内包表記は、Pythonのコードを短く書ける便利な機能ですが、使い方によっては可読性が低下したり、処理速度が悪化したりすることがあります
このセクションでは、リスト内包表記を適切に活用するためのベストプラクティスと注意点 を解説します。

リスト内包表記を使うべきケース

リスト内包表記が適しているのは、次のようなケースです。

1. シンプルなリスト作成

リスト内包表記は、リストを簡単に作成できるため、要素を単純に変換・抽出する処理 には非常に向いています。

例: 各要素を2乗する

squares = [x**2 for x in range(10)]
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

2. 条件付きのリスト作成(フィルタリング)

特定の条件を満たす要素のみを抽出する場合 にもリスト内包表記は適しています。

例: 偶数のみを抽出

evens = [x for x in range(10) if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

3. 文字列リストの変換

リスト内包表記は、文字列のリストを変換するときにも便利 です。

例: すべての文字列を大文字に変換

words = ["python", "list", "comprehension"]
uppercase_words = [word.upper() for word in words]
print(uppercase_words)  # ['PYTHON', 'LIST', 'COMPREHENSION']

4. ネストされたリストのフラット化

2次元リストを1次元に変換する場合 にも役立ちます。

例: 2次元リストの要素をフラットにする

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

リスト内包表記を使うべきでないケース

リスト内包表記は便利ですが、適さないケースもあります。

1. ネストが深いと可読性が低下する

リスト内包表記は、シンプルな処理なら読みやすくなりますが、ループが多重になると可読性が低下 します。

❌ 悪い例: 多重ループを使ったリスト内包表記

matrix = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
flattened = [num for row in matrix for subrow in row for num in subrow]

👉 ネストが深すぎて分かりにくい

✅ 改善策: 通常のforループを使う

flattened = []
for row in matrix:
    for subrow in row:
        for num in subrow:
            flattened.append(num)

2. 長すぎる処理を内包表記で書くと可読性が悪化する

リスト内包表記は 1行でシンプルに書けるのが利点 ですが、複雑な処理を入れると逆に読みにくくなります

❌ 悪い例: 複雑な条件を詰め込んだリスト内包表記

numbers = [x**2 if x % 2 == 0 else x**3 for x in range(10) if x != 5 and x % 3 != 0]

👉 条件が複雑になりすぎて読みにくい

✅ 改善策: forループを使う

numbers = []
for x in range(10):
    if x != 5 and x % 3 != 0:
        if x % 2 == 0:
            numbers.append(x**2)
        else:
            numbers.append(x**3)

リスト内包表記のパフォーマンス

1. forループと比較して処理速度が速い

リスト内包表記は、forループよりも一般的に高速 です。
Pythonの内部最適化が働くため、リストの作成が効率的に行われます。

forループ vs リスト内包表記の速度比較

import time

# 大量データでの比較
data = list(range(10**6))

# リスト内包表記
start = time.time()
squares = [x**2 for x in data]
print("リスト内包表記:", time.time() - start)

# 通常のforループ
start = time.time()
squares = []
for x in data:
    squares.append(x**2)
print("通常のforループ:", time.time() - start)

結果

  • リスト内包表記の方が高速になる傾向がある
  • ただし、リスト全体をメモリに格納するため、大量のデータではメモリ消費が増加

2. メモリ効率を考慮する場合はジェネレーター式を活用

大量のデータを扱う場合は、 リスト内包表記の代わりに「ジェネレーター式」を使うとメモリ使用量を抑えられる

# リスト内包表記(メモリを大量に消費)
squares = [x**2 for x in range(10**6)]

# ジェネレーター式(メモリ効率が良い)
squares_gen = (x**2 for x in range(10**6))

squares_gen はリストを作らず、イテレーターを返すので、メモリを節約できる。

まとめ

リスト内包表記を使うべきケース

  • シンプルなリスト作成
  • フィルタリング
  • 文字列の変換
  • 2次元リストのフラット化

リスト内包表記を避けるべきケース

  • ネストが深くなる処理
  • 条件が複雑すぎる処理
  • 可読性が極端に悪くなる場合

💡 ベストプラクティス

  • シンプルな処理にはリスト内包表記を使う
  • 複雑な処理は通常のforループを使う
  • パフォーマンスを考慮して適切に選択する
年収訴求

7. よくある質問(FAQ)

このセクションでは、リスト内包表記に関してよくある疑問や、実際に開発をする際に気をつけるべきポイント について詳しく解説します。初心者が間違いやすいポイントや、パフォーマンスに関する疑問も含めています。

Q1. ifを2回使った条件フィルタリングは可能?

A1. はい、可能ですが可読性に注意が必要です。

リスト内包表記では、ifを2回以上使うことで複雑な条件を指定することもできます。

例: 2つの条件(偶数かつ3の倍数)を満たす数値のみを抽出

filtered_numbers = [x for x in range(30) if x % 2 == 0 if x % 3 == 0]
print(filtered_numbers)  # [0, 6, 12, 18, 24]

このように、ifを連続して書くと「AND条件」のように動作します

しかし、可読性を考えるとandを使う方が分かりやすい です。

filtered_numbers = [x for x in range(30) if x % 2 == 0 and x % 3 == 0]

Q2. リスト内包表記と通常のforループのどちらを使うべき?

A2. 処理のシンプルさと可読性で選ぶのがベストです。

リスト内包表記は シンプルな処理 なら非常に有用ですが、複雑な処理では可読性が低下する可能性 があります。

例: 通常のforループを使うべきケース

# ❌ リスト内包表記では読みづらい
numbers = ["Even" if x % 2 == 0 else "Odd" if x % 3 == 0 else "Other" for x in range(10)]

# ✅ 通常の`for`ループの方が分かりやすい
numbers = []
for x in range(10):
    if x % 2 == 0:
        numbers.append("Even")
    elif x % 3 == 0:
        numbers.append("Odd")
    else:
        numbers.append("Other")

Q3. if-elseを使う場合と、ifのみを使う場合の違いは?

A3. ifのみはフィルタリング、if-elseは値の変換に使う。

ifのみ(条件を満たす要素だけを取得)

evens = [x for x in range(10) if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

→ 偶数のみを抽出し、条件を満たさない要素はリストに含まれない

if-else(条件によって異なる値を格納)

labels = ["even" if x % 2 == 0 else "odd" for x in range(10)]
print(labels)  
# ['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']

Q4. リスト内包表記の方がforループより速いの?

A4. 一般的には速いが、メモリ消費には注意が必要。

Pythonのリスト内包表記は、内部的に最適化されているため、通常のforループより高速に動作 します。

⏳ 実験:100万件のデータを処理

import time

data = list(range(10**6))

# リスト内包表記
start = time.time()
squares = [x**2 for x in data]
print("リスト内包表記:", time.time() - start)

# 通常のforループ
start = time.time()
squares = []
for x in data:
    squares.append(x**2)
print("通常のforループ:", time.time() - start)

結果

  • リスト内包表記の方が約30%~50%速いことが多い
  • ただし、リスト全体をメモリに格納するため、大量のデータではメモリ消費が増加

改善策(ジェネレーターを使う)
大量のデータを扱う場合は、 リスト内包表記の代わりに「ジェネレーター式」を使うとメモリ使用量を抑えられる

squares_gen = (x**2 for x in data)  # ()を使うとジェネレーターになる

Q5. setdictの内包表記もあるの?

A5. はい、リストだけでなくset(集合)やdict(辞書)の内包表記もあります。

set(集合)内包表記

unique_squares = {x**2 for x in range(10)}
print(unique_squares)

dict(辞書)内包表記

squares_dict = {x: x**2 for x in range(10)}
print(squares_dict)

まとめ

  • ifを2回使うことは可能だが、andを使う方が可読性が高い
  • if-elseは値を変換、ifのみはフィルタリング
  • リスト内包表記はforループより速いが、大量データではメモリ消費に注意
  • setdictにも内包表記がある

これで、Pythonのリスト内包表記とifの組み合わせに関する解説は完了です!🎉
ぜひ実際にコードを書きながら、リスト内包表記をマスターしてください!🚀