こんにちは、吉政創成 菱沼です。
今回もPythonエンジニア育成推進協会のPython 3 エンジニア認定実践試験の主教材「Python実践レシピ/技術評論社」を使って学習中です。
前回はChapter3.4アンパックを学びました。
今回はChapter3.5内包表記の項目のうち、リスト内包表記について学びます。
リスト内包表記
個人的にあまり得意ではない内包表記…。
内包表記を使用すると複数行のコードを1行で表現できるようになります。内包表記で書けるのは、リスト(list)、辞書(dict)、集合(set)ですが、ジェネレーターでも似た構文が使えるそうです。
書籍ではリスト内包表記の説明から始まっています。
まずはリスト内包表記の構文です。
| [変数を使った処理 for 変数 in イテラブルオブジェクト] [変数を使った処理 for 変数 in イテラブルオブジェクト if 条件式] |
では、通常のfor文で書いた場合と、リスト内包表記で書いた場合のサンプルコードで比較してみます
————–
P.63
for文でリストを作成
number_list = []
for i in range(10):
number_list.append(i**2)
number_list
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
リスト内包表記を使用してリストを作成
number_list = [i**2 for i in range(10)]
number_list
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
————–
記述が4行必要だったものが、内包表記を使用すると2行で済むことがよくわかります。
ただ、なぜリストの末尾に新しい要素を追加するための機能である.appendが消えたのに、リストの中に値を入れられるのかというのが気になって仕方なく、個人的に苦手意識を抱える要因になっていました。
これに関しては、そもそも内包表記自体が新たにリストや辞書、集合を作るために使用されるため、.appendを使って手動で追加するようにしなくとも、自動でリストに値を入れてくれるようになっているためだそうです。ちなみに内包表記にするコツは、まずはfor文を書いてみて、それを逆から並べ替えていくようなイメージで最初は試していくといいのだとか。確かによく見てみると、逆から並べ替えているように見えます。
if文を使った内包表記
また、最初の構文を見ていただくとわかる通り、if文を使用する場合は、ifが最後に来ます。これも私の混乱の原因だったようにも思います。
こちらがif文を使って偶数だけをリストに入る場合のサンプルコードです。
number_list = [i**2 for i in range(10) if i % 2 == 0]
number_list
[0, 4, 16, 36, 64]
これをもし、内包表記を使用せずにfor文とif文を組み合わせて書くとするとこうなります。
number_list2 = []
for i in range(10):
if i % 2 ==0:
number_list2.append(i**2)
number_list2
[0, 4, 16, 36, 64]
5行が2行に。確かに短くすみます。
とはいえ、逆とは…。どうにも納得しきれませんが、最初のうちは、ifは対応するforの後ろに書くというルールだと覚えておきたいと思います。
リスト内包表記をネストするとどうなるか、見やすさは場合による。
行数をアッといえるほどに短くできる内包表記。より多くの条件をぎゅっと出来たらなんだか素敵な予感がしなくもありません。そんなサンプルコードがこちら。
drinks = ['coffee', 'tea', 'Espresso']
sizes = ['S', 'M', 'L']
menu = [(drink, size) for drink in drinks for size in sizes]
menu
[('coffee', 'S'), ('coffee', 'M'), ('coffee', 'L'), ('tea', 'S'), ('tea', 'M'), ('tea', 'L'), ('Espresso', 'S'), ('Espresso', 'M'), ('Espresso', 'L')]
えっ・・・。と思いませんか。思いますよね。
ではこれを普通にfor文で書くとどうなるか。こうなります。
drinks = ['coffee', 'tea', 'Espresso']
sizes = ['S', 'M', 'L']
menu = []
for drink in drinks:
for size in sizes:
menu.append((drink, size))
menu
[('coffee', 'S'), ('coffee', 'M'), ('coffee', 'L'), ('tea', 'S'), ('tea', 'M'), ('tea', 'L'), ('Espresso', 'S'), ('Espresso', 'M'), ('Espresso', 'L')]
読みやすいですね。
テキストにも「多重ループをリスト内包表記で書くこと自体はできるものの、複雑すぎると可読性が下がること、そういうときにはforループに分解するようにしましょう」ということが書かれています。
やりすぎはよくない、ほどほどにということですね。
それではきりが良いので今回はこちらで終了です。
お付き合いいただきありがとうございました。
実践試験について知りたい方は以下をご覧ください。
●Python3エンジニア認定実践試験

