内包表記とは?
今回の講義はPythonの内包表記についてです。
内包表記・・・・
まったく初めて聞く単語です。
今日はしょっぱなから難しそうです(笑)
for文を用いて何か新しいリストを作成したい
そんなシチュエーションを思い浮かべてください。
例えばリストの中身を全て数値から文字列に変換したい場合です。
for文でリストの要素一つ一つ取り出し、
その要素を文字列に変換した上で
新しいリストに追加するという流れになるかと思います。
以上の流れをたったの一行で実装できるのが
内包表記らしいです。
なんだかすごい事ができそうですが、とにかく難しそうです。
とにかくコードを実際に書きながら学んでいきたいと思います。
内包表記:リストに何かしらの値を追加していく際、一行で実装できる構文構造
内包表記 例1
import random
#1~100までの数値でランダムに出力します。
random.randint(1,100)
まず、ランダムに数字を発生させる
randomをインポート。
使い方としては
random.randint(1,100)で乱数を発生させる事を確認します。
data = []
for _ in range(1000):
x = random.randint(1,100)
data.append(x)
空のリストdata = []を定義。
x = random.randint(1,100)で1~100の間で乱数を発生させxに代入
data.append(x) dataにxの値を追加。
for _ in range(1000):でその処理を1000回繰り返してリストを作成
len(data)
1000
ちゃんと1000個のデータができているかlen()で確認。
data_10x = []
for datum in data:
data_10x.append(datum*10)
data_10x[:10]
[430, 810, 260, 620, 970, 550, 680, 490, 120, 210]
先ほどつくったリストdataをもとに
data_10x = []
for datum in data:
data_10x.append(datum*10)
dataを順番にdatumに代入して、
datumを10倍した値をdata_10xにリストとして追加していきます。
リストの中身の確認のために
data_10x[:10]
[430, 810, 260, 620, 970, 550, 680, 490, 120, 210]
0~10までのリストを表記させます。
ちゃんとできています。
このランダムに発生した数値で1000個のデータが入ったリストを作成
さらに、そのリストに10を掛けた値で新たなリストを作るというコード
を内包表記では下記となります。
new_data_10x = [datum*10 for datum in data]
new_data_10x[:10]
[430, 810, 260, 620, 970, 550, 680, 490, 120, 210]
みごとに新しく作ったリストnew_data_10xも同じ結果になっています。
これが内包表記というそうです。
new_data_10x = [datum*10 for datum in data]
と書くとあまり見慣れない書式なので正直戸惑います。
ただ今西先生いわく、慣れるととても便利だそうです。
利点としては、あたりまえですが
1行表記で見やすい。さらに処理速度も速いそうです。
%%timeit :と記述すると処理速度を測定できるそうです。
実際に測ると
普通のfor 文 86.7 µs
内包表記文 49.2 µs
で内包表記のほうがずいぶんと早いのがわかりました。
内包表記 例2 if文を用いた場合
data_odd = []
for datum in data:
if datum % 2 != 0:
data_odd.append(datum)
data_odd[:10]
[43, 81, 97, 55, 49, 21, 5, 19, 65, 39]
今回の例ではif文をつかいますので、
if datum % 2 != 0:
dataからdatumに値をいれて2で割って、余りが0ではない値のみを
リストdata_oddに入れていきます。
そのデータの10番目までの数字を表記させます。
これをまた内包表記で記述します。
new_data_odd = [datum for datum in data if datum % 2 != 0]
new_data_odd[:10]
[43, 81, 97, 55, 49, 21, 5, 19, 65, 39]
見事にfor文と同じ結果を出力することができました。
前回の
new_data_10x = [datum*10 for datum in data]
は10倍するという処理はforの前に記述しましたが、
new_data_odd = [datum for datum in data if datum % 2 != 0]
if文は後ろにくるみたいです。
内包表記 例3 if else を用いた場合
条件
50>=x (50以上の整数) → そのまま表示
50<x (50未満の整数) → 100倍
この条件でfor文で記述します。
data_50 = []
for datum in data:
if datum >=50:
data_50.append(datum)
else:
data_50.append(datum*100)
data_50[:10]
[4300, 81, 2600, 62, 97, 55, 68, 4900, 1200, 2100]
これを内包表記で記述すると下記となります。
new_data_50 = [datum if datum >=50 else datum*100 for datum in data]
new_data_50[:10]
[4300, 81, 2600, 62, 97, 55, 68, 4900, 1200, 2100]
ちゃんと同じ結果が得られました。
new_data_50 = [datum if datum >=50 else datum*100 for datum in data]
ifだけのときと違い、elseが入るとfor文の前に記述するそうです。
FizzBuzz問題
1から50までの数字を出力するプログラムを書いてください。
ただし、数字の3の倍数のときは数字の代わりにFizzと出力
5の倍数のときは数字の代わりにBuzzと出力してください。
3と5の倍数のときはFizz Buzzを出力。
初めにfor文で書きます
fizz_buzz = []
for i in range(1,51):
if i%15==0:
fizz_buzz.append('FizzBuzz')
elif i%3==0:
fizz_buzz.append('Fizz')
elif i%5==0:
fizz_buzz.append('Buzz')
else:
fizz_buzz.append(i)
これを内包表記で書きます。
new_fizz_buzz = ['FizzBuzz' if i%15==0 else 'Fizz' if i%3==0 else 'Buzz' if i%5==0 else i for i in range(1,51) ]
内包表記だと、if else などの並べ方をある程度覚える必要がありそうです。
ここまで横に長いとfor文で書いた方が簡単なような気が、、、
ただ、脱初学者とあったので上級になればなるほど、
こういったコードの書き方に慣れていかないといけないんでしょうね~
いや~難しかった~
今西先生、今日も有難うございました。
コメント