Pythonには「内包表記」というコードの記述方法があります。
※おそらくリスト内包表記が一番有名だと思います。
例えば、以下の様な記述方法を見たことがないですか?
1 |
list_wk = [i*2 for i in range(1,5)] |
この場合、リストの中にfor文が入っていますよね。他の言語ではあまり見られない記述方法なのですが、Pythonでは、この記述方法を知っているとコードを簡潔に記述する事ができます。
他の方のコードを読み解く場合にも大切なスキルになると思いますので、ここで解説します。
コンテンツ
リスト内包表記
では実際にリスト内包表記を使ってみましょう。実際にサンプルを見てみると、使い方はなんとなく分かるはずです。あまり見かけない記述方法ですが、仕組みはいたってシンプルです。
for文のリスト内包表記
冒頭でも例を出しましたが、リストの中にfor文を書く事ができます。簡単なfor文を例にしてリスト内包表記をした場合とのコードを見比べてみましょう。
サンプルのfor文で生成する値は以下になります。
・1~19までの値
・1~19までの値×2の結果
単純なfor文
まずは単純なfor文のコードからです。
■Pythonコード
1 2 3 4 5 6 7 8 9 10 |
list_wk_1 = [] list_wk_2 = [] #1~19まで for i in range(1, 20): list_wk_1.append(i) list_wk_2.append(i * 2) print(list_wk_1) print(list_wk_2) |
■実行結果
1 2 |
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38] |
リスト内包表記のfor文
リスト内包表記を使ったfor文です。
■構文
1 |
[式 ループ内変数名 in イテラブルオブジェクト] |
■Pythonコード
1 2 3 4 5 |
list_wk_1 = [i for i in range(1,20)] list_wk_2 = [i*2 for i in range(1,20)] print(list_wk_1) print(list_wk_2) |
■実行結果
1 2 |
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38] |
どうでしょうか?非常にシンプルな記述方法でfor文を記述できたのが分かるかと思います。
if文のリスト内包表記
次はif文のリスト内包表記になります。
■構文
1 |
[式 ループ内変数名 in イテラブルオブジェクト if 条件式] |
■Pythonコード
1 2 |
list_wk = [i for i in range(1,20) if i < 17] print(list_wk) |
■実行結果
1 |
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] |
and条件
and条件も使えます。
■Pythonコード
1 2 |
list_wk = [i for i in range(1,20) if i > 5 and i < 17] print(list_wk) |
■実行結果
1 |
[6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] |
or条件
or条件も使えます。冗長ロジックですが。
■Pythonコード
1 2 |
list_wk = [i for i in range(1,20) if i > 5 or i > 10] print(list_wk) |
■実行結果
1 |
[6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] |
if文のリスト内包表記の注意点
リスト内包表記で注意しなければならない点があります。以下のコードと実行結果を見てみて下さい。
■Pythonコード
1 2 |
list_wk = [i*2 for i in range(1,20) if i < 10] print(list_wk) |
■実行結果
1 |
[2, 4, 6, 8, 10, 12, 14, 16, 18] |
リスト内包表記の中ではfor文とif文が使われていますが、if文の判定が先に行われている事が分かります。1~10までの数値を選出した上で、×2という処理になっている訳です。
コードの処理の順番を分かっていないと、コードを読む上で混乱してしまうので要注意です。
※この場合のif文は「後置if文」などと呼ばれます。
else文のリスト内包表記
else文になると「if文」の場合とは位置などが変わります。分かりにくい。。
■else文の構文
1 |
[真の場合の値 if 条件式 else 偽の場合の値 for ループ内変数名 in イテラブルオブジェクト] |
■Pythonコード(list_wk_2 を設定する際にリスト内包表記のelseを使用しています)
1 2 3 4 |
list_wk_1 = [i for i in range(10)] list_wk_2 = ['偶数' if i % 2 == 0 else '奇数' for i in range(10)] print(list_wk_1) print(list_wk_2) |
■実行結果
1 2 |
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ['偶数', '奇数', '偶数', '奇数', '偶数', '奇数', '偶数', '奇数', '偶数', '奇数'] |
集合内包表記
Pythonでは集合内包表記も記述ができます。
記述方法はリストの場合と全く一緒です。
リストの時と全く同じ様にfor文を使った記述方法をしてみましょう。
■構文(for文の場合)
1 |
{式 ループ内変数名 in イテラブルオブジェクト} |
■Pythonコード
1 2 |
set_wk = {i for i in range(20)} print(set_wk) |
■実行結果
1 |
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19} |
ジェネレータ式内包表記
集合内包表記も記述ができます。
記述方法はリストの場合と同じですが、[]でななく()でくくります。
また戻り値はイテレータと呼ばれる集合データの構造値となります。
一般的にはあまり使いません。。。
■構文(for文の場合)
1 |
(式 ループ内変数名 in イテラブルオブジェクト) |
■Pythonコード
1 2 |
gen_wk = (i*2 for i in range(20)) print(gen_wk) |
■実行結果
1 |
<generator object <genexpr> at 0x7fd11c1a6f10> |
辞書内包表記
辞書内包表記というものもあります。
辞書の場合も内包表記が可能です。
リストが分かっていれば、わりと直観的な記述方法なので分かりやすいと思います。
keyの値をdict01、dict02、dict03と増やしながら、同時にvalueも1、2、3と増やすコードを書いてみます。
■Pythonコード(sortedはソートをするだけの関数です)
1 2 3 |
dict_wk = {"dict" + str(i): i for i in range(0, 20)} dict_wk = sorted(dict_wk.items(), key=lambda j: j[1]) #valueでソート print(dict_wk) |
■実行結果
1 |
[('dict0', 0), ('dict1', 1), ('dict2', 2), ('dict3', 3), ('dict4', 4), ('dict5', 5), ('dict6', 6), ('dict7', 7), ('dict8', 8), ('dict9', 9), ('dict10', 10), ('dict11', 11), ('dict12', 12), ('dict13', 13), ('dict14', 14), ('dict15', 15), ('dict16', 16), ('dict17', 17), ('dict18', 18), ('dict19', 19)] |
まとめ
様々な内包表記について解説をしてきました。大きく以下の4つの内包表記がありましたね。
・リスト内包表記
・集合内包表記
・ジェネレータ内包表記
・辞書内包表記
ただ、実際に使用するのは、やはりリスト内包表記かもしれません。
if文、else文を使うケースなども紹介をしましたが、あまりに可読性が低い場合は、無理して使う必要は無いと思います。ただ、他の方が書いたコードを読む場合には必要な知識になりますので、今回ご紹介した内容についてはしっかりと把握しておきたい所です。特にfor文とif文を組み合わせたリスト内包表記については結構使用頻度が高いです!