【Python】内包表記を極めよう【基本講座】
Pythonには、内包表記という独時の記法があります。コードの節約だけでなく使用メモリも抑えれるという素晴らしい記法なので、是非覚えてマスターしてください。
Pythonで扱う型別 内包表記
そもそも内包表記は、リストの要素を効率的に生成する方法として用意されたものです。それぞれの型でやり方が少しだけ異なりますが、根本はリストの要素を取り出すということです。
リスト型の内包表記
よく例に出される問題をみてみましょう。
問題:
0~10までの偶数を2乗した数値を要素とするリストを作成せよ。
まずは、今までの知識で愚直に書きましょう。
1 2 3 4 5 6 7 8 |
l = [] for i in range(0, 11, 2): l.append(i ** 2) print(l) >> [0, 4, 16, 36, 64] |
こういうコードを大量に書くとどうしてもコード量が膨れてしまい、後で見るときに大変になります。そこでコードの最適化を考えるのですが、考案されたのが内包表記です。内包表記で書くとこんなに短く書くことができます。
1 2 3 4 5 |
l = [i** 2 for i in range(0, 11, 2)] print(l) >> [0, 4, 16, 36, 64, 100] |
どうですか?かなりスッキリして見やすくなったんじゃないでしょうか?
しかし、あなたは、この変換を自在に操れるようになる必要があります。
いきなり内包表記を書いても「i ** 2」が何を表しているのか、もしかするとわからないかもしれません。まずは、愚直に空リストを宣言してからfor文でappend()していくコードを書いていることで、内包表記の恩恵はさらに受けれるのだと思います。
内包表記の万能なところは、それだけではありません。
for文のあとに条件式を立てることができます。
次のような問題を考えてみてください。
問題:
整数が格納されたリストから3の倍数のみを取り出してください。
1 2 3 4 5 6 7 |
l1 = [1, 3, 7, 9, 10, 15, 20, 30] l2 = [i for i in l1 if(i % 3) == 0] print(l2) >> [3, 9, 15, 30] |
こんな感じでfor文のあとに追加するだけです。
では、これを愚直に書き直してみましょう。
1 2 3 4 5 6 7 8 9 10 |
l1 = [1, 3, 7, 9, 10, 15, 20, 30] l2=[] for i in l1: if not(i%3):l2.append(i) print(l2) >> [3, 9, 15, 30] |
簡単でしたか?
慣れてくると脊髄反射レベルで書けるようになりますので、変換練習は数をこなしてください。
タプル型の内包表記
タプル型の内包表記と言ってもList[Tuple]といった感じになります。
つまりリスト型の時と同じ感じで書けるので、名前負けせずにゆっくり今までの知識で解読できます。
よくある例題で確認しましょう。
問題:
(“名前”, “性別”)を要素とするリストがあるとき、男だけを取り出しなさい。
1 2 3 4 5 6 7 8 9 10 11 |
lt1 = [("A", "女"), ("B", "男"), ("C", "女"), ("D", "男")] lt2 = [] for i in lt1: if i[1] == "男": lt2.append(i[0]) print(lt2) >> ['B', 'D'] |
まずは、愚直に内包表記なしで書きました。
今回は、名前のみ取り出しましたが、当然タプル要素で取り出すこともできます。
1 2 3 4 5 6 7 8 9 10 11 |
lt1 = [("A", "女"), ("B", "男"), ("C", "女"), ("D", "男")] lt2 = [] for i in lt1: if i[1] == "男": lt2.append(i) print(lt2) >> [('B', '男'), ('D', '男')] |
append()でi だけ指定するだけで良いです。
では、内包表記はどう書くのでしょうか?
1 2 3 4 5 6 7 8 9 10 11 |
lt1 = [("A", "女"), ("B", "男"), ("C", "女"), ("D", "男")] lt2 = [] for i in lt1: if i[1] == "男": lt2.append(i) print(lt2) >> ['B', 'D'] |
簡単でしたね。いろいろな問題を作って自在に変換できるように訓練してください。
辞書型の内包表記
次に辞書型の内包表記ですが、これは今までとほんの少し表記が変わります。辞書型なので[]のかわりに、{}を使うだけですが。
では、問題を解いていきましょう。
2つのリストがあり、それを辞書にしてみましょう。
1 2 3 4 5 6 7 8 9 |
l1 = ["A", "B", "C", "D"] l2 = ["1", "2", "3", "4"] d = {i:t for i in l1 for t in l2} print(d) >> {'A': '4', 'B': '4', 'C': '4', 'D': '4'} |
いままでの知識で内包表記を書いてみましたが、上手くいきません。
キーか値どちらかが固定値なら上手くいきそうです。
どうやらこの書き方では上書きされるみたいですね。
そこでzip()関数を使うとうまくいきます。
1 2 3 4 5 6 7 8 9 |
l1 = ["A", "B", "C", "D"] l2 = ["1", "2", "3", "4"] d = {i:t for i,t in zip(l1, l2)} # l1はi l2はt に print(d) >> {'A': '1', 'B': '2', 'C': '3', 'D': '4'} |
zip()関数に関してですが、引数が2しかダメではありません。3つでも4つでも複数取れます。
では、l1とl2の要素が異なる場合。どうなるのでしょうか?
エラーにはならず、要素の少ない方に合わせてペアにします。
Pythonおすすめ書籍
最初の2冊は初心者向けです。Effectiv Pythonはこの2冊を終えてから読むとかなりわかりやすく感動できると思います。
|
|
|