慣れないとリストの内包表記って頭が変になりませんか。そんな場合は、図で感覚をつかみましょう。リストの内包表記は、for文やif文を使ったリストの作成がたった1行で書けてしまう便利な表記です。だから、うまう使いこなせばすっきりした見やすいコードを書くことができます。
1.「リスト内包」と「入れ子のリスト内包」の比較
リストの内包表記は、慣れれば難しくありません。なお、リストの中にリストがあるような「入れ子」にした「入れ子のリスト内包」と、入れ子にしないただの「リスト内包」を混同しないように整理しましょう。
(1) 表記の比較
「リスト内包」は内包表記を使わない「通常表記」との違いを図を使ってイメージできることが大切です。「内包表記」をfor文やif文を使った「通常表記」に置き換えられれば簡単に理解できます。
(a)ただの「リスト内包」
単純に「内包表記」の左側が「通常の表記」の外側になります。
(b)「入れ子のリスト内包」
リストの[ ]の中での実行順序は入れ子ではない場合と同じです。しかし、[ ]で区切られていますので、[ ]で区切られた外側から順番に実行されるのが入れ子がない場合との違いです。
(2)出力結果の違い
上記(1)のコードの図を、以下に示します。「入れ子のリスト内包」は出力も入れ子になっていますが、ただの「リスト内包」は出力が入れ子になっていません。それが大きな違いです。
(a)ただの「リスト内包」
ただの「リスト内包」では、出力結果も入れ子になっていません。
#コード01-1 (ただの「リスト内包」)
a=[i * 3 + j for i in range(2) for j in range(-1,2) if (i * 3 + j) > 0 ]
print(a)
#コード01-2 (通常の表記への書き換え)
a=[]
for i in range(2):
for j in range(-1, 2):
if (i * 3 + j) > 0 :
a.append(i * 3 + j)
print(a)
#出力01
[1, 2, 3, 4]
(b)「入れ子のリスト内包」
「入れ子のリスト内包」では、出力結果が入れ子になっています。
#コード02-1 (入れ子のリスト内包)
a=[[i * 3 + j for j in range(-1,2) if (i * 3 + j) > 0] for i in range(2) ]
print(a)
#コード02-2 (通常の表記への書き換え)
a=[]
for i in range(2):
tmp=[]
for j in range(-1, 2):
if (i * 3 + j) > 0:
tmp.append(i * 3 + j)
a.append(tmp)
print(a)
#コード02
[[1], [2, 3, 4]]