7
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

内包表記(List Comprehension)の理解

Last updated at Posted at 2021-08-13

#はじめに

Pythonの内包表記について、自分で分かったことを記録しておきます。

#内包表記とは?

最初、内包表記という単語を耳にした時に、正直にピンときませんでした。内包という漢字が、肉まん+包むに見えて、何か横浜中華街の新しい流行りの食べ物?との印象でした。
オリジナルの英語表記では、内包表記をList Comprehensionと言います。なるほど、リストを作成するときに使うものだったんですね。

  • リストを作成する
  • for文if文が一行になった形式
  • single for loopだけではなく、double for loopにも使える。
  • 計算速度が速くなる

一言で表すと、下記の文章に変えられます。

###内包表記は、リストを作成するfor loopを理解しやすい一行にコードを圧縮するもので、計算速度が速い。###

それでは、順番に事例を書いてみます。

#1.for loop

0から4までの数字で構成するリストを作成するコードです。
既存表記と内包表記の順番にコードを記します。

既存表記.py
list = []
for i in range(5):
    list.append(i)

print(list)

#結果
[0, 1, 2, 3, 4]
内包表記.py
# [式 for 任意の変数名 in イテラブルオブジェクト]

list_n = [ i for i in range(5)]
print(list_n)

#結果
[0, 1, 2, 3, 4]

#2.for loop (少し複雑)
リストを作成するときに、演算を加えます。
今回は、0から4まで、それぞれの二乗した数字をリストにするコードです。

既存表記.py
list = []
for i in range(5):
    val_new = i**2
    list.append(val_new)

print(list)

#結果
[0, 1, 4, 9, 16]

内包表記.py
# [式 for 任意の変数名 in イテラブルオブジェクト]
list_n = [ i**2 for i in range(5)]
print(list_n)

#結果
[0, 1, 4, 9, 16]

#2.for loop + if

0から20までの偶数で構成するリストを作成するコードです。

既存表記.py

list = []

for i in range(20):
    if i%2 ==0:
        list.append(i)

print(list)

#結果
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

内包表記.py
#[式 for 任意の変数名 in イテラブルオブジェクト if 条件式]
list_n = [ i for i in range(20) if i%2 ==0]
print(list_n)

#結果
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

#3.double for Loop
次は2重ループです。画素数(5X5)の画像を想像してください。(行X列)の計算結果のリストを作成するコードです。

既存表記.py
list = []
for row in range(5):
    for col in range(5):
        list.append(row * col)

print(list)

#結果
[0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 2, 4, 6, 8, 0, 3, 6, 9, 12, 0, 4, 8, 12, 16]

内包表記.py
list_n = [ row * col for row in range(5) for col in range(5)]
print(list_n)

#結果
[0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 2, 4, 6, 8, 0, 3, 6, 9, 12, 0, 4, 8, 12, 16]

#4.double for loop + if

今度は、偶数の行と奇数の列だけで、計算するリストです。

既存表記.py
list = []
for row in range(5):
    if row %2 ==0:
        for col in range(5):
            if col %2 ==1:
                list.append(row * col)

print(list)

#結果
[0, 0, 2, 6, 4, 12]

if文の位置に注目してください。基本的に、上記の既存表記を1行に伸ばした書き方をしています。(これを覚えると内包表記はもう大丈夫かと。)

内包表記.py
list_n = [ row * col for row in range(5) if row%2 == 0 for col in range(5) if col %2 ==1]
print(list_n)
#結果
[0, 0, 2, 6, 4, 12]

#5. 計算速度比較

IPythonの##%%time%%で計測しました。

既存表記.py
%%time 

list = []
for i in range(1000000):
    list.append(i)

CPU times: user 206 ms, sys: 33.2 ms, total: 239 ms
Wall time: 242 ms

内包表記.py
%%time 
# [式 for 任意の変数名 in イテラブルオブジェクト]

list_n = [ i for i in range(1000000)]

CPU times: user 112 ms, sys: 34 ms, total: 146 ms
Wall time: 146 ms

内包表記の計算速度が速いです。二重for loop + if文の計算速度も見てみましょう。

既存表記.py
%%time

list = []
for row in range(5000):
    if row %2 ==0:
        for col in range(5000):
            if col %2 ==1:
                list.append(row * col)

CPU times: user 2.27 s, sys: 116 ms, total: 2.39 s
Wall time: 2.39 s

内包表記.py
%%time 

list_n = [ row * col for row in range(5000) if row%2 == 0 for col in range(5000) if col %2 ==1]

CPU times: user 1.4 s, sys: 106 ms, total: 1.51 s
Wall time: 1.52 s

##まとめ

  • 内包表記は、リストを作成するときに使う効率的なコードの書き方です。
  • 無暗に書き方を覚えるより、既存のコードと比較してみることで、内包表記の書き方が理解しやすいです。
  • 慣れると内包表記のほうが読みやすいことにと気付きます。
  • 計算速度も速いです。まさに一石二鳥。
7
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?