内包記法(list comprehensionなど)
リスト内包記法(list comprehension)
リスト内包記法は、forループを使ってリストを作る作業を簡単に書ける構文です。例えば、以下のように最近の睡眠時間がリストに入っているとします。
sleepHrs = [8.5, 7.25, 6.33, 3.25, 8.75, 10.33, 11.1]
で、それぞれの睡眠時間を四捨五入して、整数のリストを作りたいとします。ループを使ってやると次のようになります。
roundedSleepHrs = []
for sleepHr in sleepHrs:
roundedSleepHrs.append( round(sleepHr) )
roundedSleepHrsが整数のリストで、[8, 7, 6, 3, 9, 10, 11]となります。
内包記法を使うと同じ作業を以下のように1行で書けます。
roundedSleepHrs = [round(sleepHr) for sleepHr in sleepHrs]
[と]で囲まれている部分は、新しいリストを作ることを意味しています。この部分の中身は、もともとの(普通のforループを使った)プログラムと比べると理解できると思います。for sleepHr in sleepHrsの部分はforループの書き方と同じです。つまりリストsleepHrsの中のデータ(要素)をsleepHrで表しています。そして、そのsleepHrを関数round()に渡して四捨五入し、その結果を新しいリストの要素として加えています。1番目のデータ8.5をround()に渡して、四捨五入された8をリストに追加、2番目のデータ7.25をroundに渡して、四捨五入された7をリストに追加・・・というのを最後のデータまで続けます。すると[8, 7, 6, 3, 9, 10, 11]というリストが作られます。
初めて読むときはびっくりするかもしれませんが、普通のforループを使ったプログラムを思い浮かべながら理解するようにしてください。何回か読み書きするうちにだんだん慣れてきて、そのうちforループをわざわざ書くのが面倒に感じてきます。
また、内包記法にはif文を追加できます。以下のようにすると、7時間より少ない睡眠時間だけを取り出して四捨五入します。
roundedShortSleepHrs = [round(sleepHr) for sleepHr in sleepHrs if sleepHr < 7]
これは以下のプログラムと同じことをします。
roundedShortSleepHrs = []
for sleepHr in sleepHrs:
if sleepHr < 7:
roundedShortSleepHrs.append( round(sleepHr) )
もう少し進んだ使い方も書いておきます。ここからは、1週間分の睡眠時間だけでなく2週間分の睡眠時間を使うことにします。以下のようにリストのリスト(a list of lists)を作って、1週間分のデータごとに別のリストに入れます。
weeklySleepHrs = [ [8.5, 7.25, 6.33, 3.25, 8.75, 10.33, 11.1],
[6, 6.75, 7.33, 7.25, 5.75, 8.33, 8.25] ]
最初のリストに入っている8.5, 7.25,・・・が1週間目の睡眠時間、2番目のリストに入っている6, 6.75,・・・が2週間目の睡眠時間です。このデータを使って1週間ごとの平均睡眠時間を計算し、それを四捨五入するのが以下のプログラムです。
from statistics import mean
weeklySleepHrsAvg = []
for sleepHrs in weeklySleepHrs:
weeklySleepHrsAvg.append( round(mean(sleepHrs)) )
リストweeklySleepHrsAvgには[8, 7]が入り、これは1週間目の平均睡眠時間が8時間、2週間目は7時間ということです。このプログラムを内包記法で書くと以下のようになります。
weeklySleepHrsAvg = [round(mean(sleepHrs)) for sleepHrs in weeklySleepHrs]
さらに以下のようにすると、1週間ごとに最短の睡眠時間と最長の睡眠時間も計算します。
[ [round(mean(sleepHrs)), round(min(sleepHrs)), round(max(sleepHrs))]
for sleepHrs in weeklySleepHrs]
結果は[[8, 3, 11], [7, 6, 8]]となります。1つめのリスト[8, 3, 11]は、1週間目の平均が8時間、最短が3時間、最長が11時間という意味です。2つめのリスト[7, 6, 8]は、2週間目の平均、最短、最長が7、6、8という意味です。
ディクショナリー内包記法(dictionary comprehension)
ディクショナリー内包記法は、forループを使ってディクショナリーを作る構文です。リスト内包記法を理解できれば、ディクショナリー内包記法の読み書きも基本的に同じことです。