数弱の文系大学生によるブログです。

Python、Webデザイン関連の記事を投稿していけたらなと思っています。

備忘録的なブログなので、読みにくい文章だと思います。ご了承ください。

Python3の復習(内包表記)

こんにちは。

かにたまごです。
特に報告等ないのでサクッと進めていきます。


今回は

  • 内包表記

について、復習していきたいと思います。
短くなりそうです。


今までのPython3 復習履歴は以下の通り。

  1. 数値・文字列
  2. リスト・タプル
  3. 辞書・集合
  4. if文・while文・for文

内包表記

一つ以上のイテレータからPythonデータ構造をコンパクトに作成できる形式。
参考書の説明ほぼ丸パクリ(;^ω^)

  • リスト内包表記

カーネルとかにバンバン出てくるリスト内包表記。


例えば、1~10までの数値リストを作るのに以下のような方法がある。

一番面倒くさい方法。

num_list = []
num_list.append(1)
num_list.append(2)
num_list.append(3)
num_list.append(4)
num_list.append(5)
num_list.append(6)
num_list.append(7)
num_list.append(8)
num_list.append(9)
num_list.append(10)


for文を利用する方法。

num_list = []
for num in range(1, 11):
    num_list.append(num)


イテレータオブジェクトをリスト化する方法。

num_iter = range(1, 11)
num_list = list(num_iter)


どのコードでも同じ結果になるが、リスト内包表記を利用した方がPythonらしいコードになるらしい。

num_list = [num for num in range(1, 11)]

確かに簡潔なコードだし、パっと見で分かりやすい、かな?
少なくとも list(range(1, 11)) よりは分かりやすい気がする。


リスト内包表記には、条件式も追加することができる。

#偶数のみ選択
even_list = [num for num in range(1, 101) if num % 2 == 0]


こういうコードも何とか一行で書ける。
分かりやすさはない。素直に純粋なfor文使うなりした方が良さそう。

#50未満 -> 赤
#50以上80未満 -> 黄色
#80以上 -> 青
num_list_ = [num for num in range(-50, 101) if num > 0]
color_list_ = ["blue" if num >= 80 else "yellow" if num < 80 and num >= 50 else "red" for num in num_list]

素直版コード。

num_list = []
for num in range(-50, 101):
    if num > 0:
        num_list.append(num)

color_list = []
for num in num_list:
    if num >= 80:
        color_list.append("blue")
    elif num >= 50 and num < 80:
        color_list.append("yellow")
    else:
        color_list.append("red")

print(color_list_ == color_list_)
出力 -> True


複数条件の部分で躓いた点。

リスト内包表記の条件式では、ifとelseしか使用できない―elifが使用できない
3つの条件で分岐させたい場合、if文を二つ用意する

上記のコードでいうと
["blue" if num >= 80 else "yellow" if num < 80 and num >= 50 else "red" for num in num_list]
の太字部分(else)で一つ目のif文に当てはまった処理をスキップ。以降は普通のif文。
つまりは、こういう感じの処理?

color_list = []
for num in num_list:
 #80以上だったら、値を追加して処理をスキップ。
 #80以上に当てはまらない場合は2つ目のif文以降が適用される。
    if num >= 80:
        color_list.append("blue")
        continue
    if num >= 50 and num < 80:
        color_list.append("yellow")
    else:
        color_list.append("red")


うーん。無理やり理解した感じが否めない・・・。
モヤモヤするなぁ。


二重ループも可能。

#九九
nums = [(num1, num2) for num1 in range(1, 10) for num2 in range(1, 10)]
for num1, num2 in nums:
    result = num1 * num2
    print(num1, "*", num2, "=", result)
  • 辞書包括表記

リスト内包表記と同じような形式で記述できる。

num_list_ = [num for num in range(1, 101)]
color_list_ = ["blue" if num >= 80 else "yellow" if num < 80 and num >= 50 else "red" for num in num_list]
color_dict = {color: color_list_.count(color) for color in set(color_list_)}
print(color_dict)

出力 ->
{'red': 49, 'blue': 21, 'yellow': 30}
  • 集合内包表記

集合にも内包表記ってあったんだ・・・。

num_set = {num for num in range(1, 100) if num % 3 == 1}


リスト、辞書、集合ときたらタプルもあるのかって思うけど、実はないらしい。

something = (num for num in range(1, 101) if num % 2 == 0)

こう書くと、ジェネレータオブジェクトが生成される。

<generator object <genexpr> at 0x0031EC90>

for文で処理したり、リスト化することができる。

for num in something:
    print(num)

出力1 ->
2
4
6
8
10
12
(100まで)


lists = list(something)
print(lists)

出力2 ->
[2, 4, 6, 8, 10...(100まで)]

補足説明
ジェネレータは一度だけしか実行できない。
文字列やリストなどのオブジェクトはメモリ内に値を格納するが、ジェネレータはイテレータに渡す際にその場で一つずつ生成するため過去の値を覚えていない。

結局それなりの量になってしまった・・・。
短いコードも良いけど、やっぱり人が見て分かりやすいコードが書けるようになりたい。


以上です。