#はじめに
Pythonの内包表記について、自分で分かったことを記録しておきます。
#内包表記とは?
最初、内包表記という単語を耳にした時に、正直にピンときませんでした。内包という漢字が、肉まん+包むに見えて、何か横浜中華街の新しい流行りの食べ物?との印象でした。
オリジナルの英語表記では、内包表記をList Comprehensionと言います。なるほど、リストを作成するときに使うものだったんですね。
- リストを作成する
- for文とif文が一行になった形式
- single for loopだけではなく、double for loopにも使える。
- 計算速度が速くなる
一言で表すと、下記の文章に変えられます。
###内包表記は、リストを作成するfor loopを理解しやすい一行にコードを圧縮するもので、計算速度が速い。###
それでは、順番に事例を書いてみます。
#1.for loop
0から4までの数字で構成するリストを作成するコードです。
既存表記と内包表記の順番にコードを記します。
list = []
for i in range(5):
list.append(i)
print(list)
#結果
[0, 1, 2, 3, 4]
# [式 for 任意の変数名 in イテラブルオブジェクト]
list_n = [ i for i in range(5)]
print(list_n)
#結果
[0, 1, 2, 3, 4]
#2.for loop (少し複雑)
リストを作成するときに、演算を加えます。
今回は、0から4まで、それぞれの二乗した数字をリストにするコードです。
list = []
for i in range(5):
val_new = i**2
list.append(val_new)
print(list)
#結果
[0, 1, 4, 9, 16]
# [式 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までの偶数で構成するリストを作成するコードです。
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]
#[式 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列)の計算結果のリストを作成するコードです。
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]
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
今度は、偶数の行と奇数の列だけで、計算するリストです。
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行に伸ばした書き方をしています。(これを覚えると内包表記はもう大丈夫かと。)
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%%で計測しました。
%%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
%%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文の計算速度も見てみましょう。
%%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
%%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
##まとめ
- 内包表記は、リストを作成するときに使う効率的なコードの書き方です。
- 無暗に書き方を覚えるより、既存のコードと比較してみることで、内包表記の書き方が理解しやすいです。
- 慣れると内包表記のほうが読みやすいことにと気付きます。
- 計算速度も速いです。まさに一石二鳥。