【Python入門・応用講座】15.内包表記|一定のルールでリストや辞書、集合を作る方法(初心者にもわかりやすく)

こんにちは。キノコードです。
この動画では、Pythonの内包表記について説明します。

内包表記とは

内包表記とは、一定のルールに従った要素を持つリスト、集合、辞書などを作成するための簡潔な記述方法です。
例えば、0から10までの数値を要素に持つリストを作成したいときなどに使われます。
for文を使って作成することもできますが、for文はインデントを伴った繰り返し処理が必要なため、複数行のコードを記述する必要があります。
一方、内包表記を使うと、同じ内容を1行のコードで書けます。
更に、プログラムの処理も速くなるのでシンプルなコードを書く場合には積極的に取り入れましょう。

リスト内包表記

最初にリスト内包表記について説明します。
例えば、0から4の整数を要素に持つリストを作成する場合を考えます。

l1 = []
for i in range(5):
    l1.append(i)

l2 = [i for i in range(5)]

print(l1)
print(l2)

違いがわかりやすいように、for文で書く場合と比較してみましょう。
for文で書く場合、まず空のリストを変数l1に代入します。
次にfor、カウンタ変数、in、そしてrange関数を書き、引数に5を渡します。
インデントを下げて、変数l1のappendメソッドを使用してカウンタ変数を加えていきます。
これで0から4の整数を要素に持つリストを作成できます。

これをリスト内包表記で書いてみます。
角括弧の中にカウンタ変数、その後はfor文と同様に、for、カウンタ変数、in、そしてrange関数を書き、引数に5を渡します。
これを変数l2に代入し、完成です。
forから後ろの文で0から4の数値を順に取り出し、それを先頭のカウンタ変数に代入するイメージです。
for文で作成したリストと、内包表記で作成したリストをそれぞれ表示してみましょう。
実行します。
同じリストを作成できました。
このようにfor文を使うと複数行に渡るコードも、リスト内包表記を使うと1行で書けます。

また、forの前のカウンタ変数を計算式にすることもできます。

l = [i / 2 for i in range(5)]

print(l)

カウンタ変数を2で割った値を要素に持つリストを作成してみましょう。
実行します。
0から4までの数値を2で割った値を要素に持つリストを作成できました。

集合内包表記

次に集合内包表記について説明します。
集合内包表記はリスト内包表記と書き方は同じで、角括弧の代わりに波括弧を使用します。
具体例で確認してみましょう。

s = {i for i in range(5)}

print(s)

0から4の整数を要素に持つ集合を作成します。
波括弧の中にカウンタ変数のiを書き、その後はfor文と同様に、for、i、in、そしてrange関数を書き、引数に5を渡します。
これを変数sに代入し、結果を確認してみましょう。
実行します。
集合を作成できました。

また、リスト内包表記と同様にforの前のカウンタ変数を計算式にすることもできます。

s = {i / 2 for i in range(5)}

print(s)

カウンタ変数を2で割った値の集合を作成してみましょう。
実行します。
0から4までの数値を2で割った値の集合を作成できました。
ただし集合の性質上、要素に順番はないことに注意しましょう。

辞書内包表記

次に辞書内包表記について説明します。
辞書はキーと値を持つので、辞書内包表記でもキーと値を書きます。
具体例で確認してみましょう。

d = {i : i * 2 for i in range(5)}

print(d)

波括弧の中にキーと値を書きます。
今回はキーにカウンタ変数を代入し、値にカウンタ変数の2倍の値を代入します。
その後はfor文と同様に、for、i、in、そしてrange関数を書き、引数に5を渡します。
これを変数dに代入し、結果を確認してみましょう。
実行します。
辞書を作成できました。

条件付き内包表記

次に条件付きの内包表記について説明します。
内包表記の中でifを使うと、要素の条件を設定できます。
ifのみを使う場合と、ifとelseを使う場合で条件を書く位置が異なります。
具体例で確認してみましょう。

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

print(l)

まず、ifのみを使う場合について説明します。
0から9までの偶数を要素に持つリストを作成します。
角括弧の中にカウンタ変数のiを書き、その後ろにfor、i、in、そしてrange関数を書き、引数に10を渡します。
これで0から9までの整数を取り出し、iに代入するイメージです。
その後ろにif、i、%(パーセント)、2、==(イコール2つ)、0と書きます。
こうすることで、iを2で割った余りが0の数、すなわち偶数だけを要素に持つリストを作成できます。
これを変数lに代入し、結果を確認してみましょう。
実行します。
0から9までの偶数を要素に持つリストを作成できました。

d = {i : "even" if i % 2 == 0 else "odd" for i in range(10)}

print(d)

次に、ifとelseを使う場合について説明します。
今度は0から9までの整数をキーとして取り出し、偶数には「even」奇数には「odd」という値が付いた辞書を作成します。
ifとelseを使う場合は、forよりも先に条件を書きます。
まず、波括弧の中にカウンタ変数のiと:(コロン)を書きます。
その後に"even"、if、i、%(パーセント)、2、==(イコール2つ)、0、そしてelse、"odd"と書きます。
これはレッスン11で説明した条件式です。
最初に、条件に当てはまったときの結果を書き、その後にif、条件、elseと書き、最後に条件に当てはまらなかったときの結果を書きます。
そして最後にfor、i、in、そしてrange関数を書き、引数に10を渡します。
こうすることで、偶数には「even」奇数には「odd」という値が付いた辞書を作成できます。
これを変数dに代入し、結果を確認してみましょう。
実行します。
0から9までの整数をキーとして、偶数には「even」奇数には「odd」という値が付いた辞書を作成できました。

内包表記のネスト

最後に内包表記のネストについて説明します。
レッスン11ではfor文のネストについて説明しました。
内包表記でもforループをネストさせることができます。
具体例で確認してみましょう。

l1 = []
for i in (10, 100, 1000):
    for j in (1, 2, 3):
        l1.append(i + j)

l2 = [i + j for i in (10, 100, 1000) for j in (1, 2, 3)]

print(l1)
print(l2)

10、100、1000から一つずつ値を取り出し、1、2、3から一つずつ取り出した値と足し算をします。その結果を要素に持つリストを作成します。
わかりやすいように、for文をネストして作成する方法と比較してみましょう。
for文で書く場合は、空のリストを変数l1に代入し、for、i、in、括弧、10、100、1000として外側のループを書きます。
インデントを下げてfor、j、in、括弧、1、2、3として内側のループを書きます。
さらにインデントを下げて、l1のappendメソッドを使用してi+jの結果を加えていきます。
これで完成です。

これをリスト内包表記で書いてみます。
角括弧の中にカウンタ変数を足し算したi+jを最初に書きます。
そしてfor、i、in、括弧、10、100、1000として外側のループを先に書きます。
その後にfor、j、in、括弧、1、2、3として内側のループを書きます。
これを変数l2に代入し、完成です。
結果を確認してみましょう。
実行します。
同じリストを作成できました。
このように内包表記でもforループをネストさせることができます。
ただし、式や変数が複雑になるとコードが読みにくくなります。
コードの読みやすさとのバランスを考えながら、どちらの方法でコードを書くか判断しましょう。