目次
Forループ(1)基本のループと応用技
今回は、Pythonのforループの書き方を整理します。
基本(1):整数のカウントアップ・ダウン
C言語だと「for i=0;i<10;i++{}」でループを回すようなパターンです。
# 0-9 for i in range(10): print(i) # 9-0 for i in range(9,-1,-1): print(i) # 1-10 for i in range(1,11): print(i)
基本は「range(start,end,step)」です。
startは省略されると「0」、stepは省略されると「1」です。
endは指定された数字のひとつ手前まで繰り返します。
だから、endが10だと、iには9まではいりますし、逆に減っていくパターンだと、0まで繰り返したい場合はendは「-1」にしないといけないわけです。
ちなみに。
上記の「range()」は、整数専用です。
浮動小数点数は使えません。
基本(2):少数のカウントアップ・ダウン
少数の1.0から3.0まで0.1きざみでループさせたい時は、「range()」ではなく、「numpy.arange()」を使う必要があります。
import numpy as np for n in np.arange(1.0,3.0,0.1): print(n)
これで、1.0から2.9までの繰り返しになります。
基本(3):listをループで処理:値だけが欲しい場合
a = ['a','b','c','d','e','f','g'] for x in a: print(x)
inだけです。
'a'、'b'などの値が順に変数(x)にはいってくる感じです。
今度は値だけでなく、添え字も一緒に欲しい場合。
a = ['a','b','c','d','e','f','g'] for i,name in enumerate(a): print(i,":",name)
基本(4):listをループで処理:添え字と値をセットで取得
enumerate()を使うと、添え字と値の両方を取得できます。
上記の例だと、「i」に0,1,2・・の添え字、「name」に'a','b','c'・・の値が順番にセットされます。
結果出力はこんな感じです。
0 : a
1 : b
2 : c
3 : d
4 : e
5 : f
6 : g
range(len(a))よりスマートなので、自分はこちらを愛用してます。
応用(1):型複数のリストをネストしたループで処理
例えば、以下のように4つのリストがあるケースを考えます。
a = ['a','b','c']
b = ['5','6','7']
c = ['d','e','f']
d = ['1','2','3']
それらを総当たりで組み合わせて処理しないといけないような場合、普通に考えたり、こんな感じにループを重ねます。
a = ['a','b','c'] b = ['5','6','7'] c = ['d','e','f'] d = ['1','2','3'] for w in a: for x in b: for y in c: for z in d: print(w,x,y,z)
応用(2):itertoolsを使ってネストしたループを処理
itertoolsを使うと、上記と同じことが、以下のように、かなりスマートにかけます。
import itertools as itr a = ['a','b','c'] b = ['5','6','7'] c = ['d','e','f'] d = ['1','2','3'] for w,x,y,z in itr.product(a,b,c,d): print(w,x,y,z)
これは、for文の深さが深くなればなるほど差がでます。
ネストが深くなりそうなら、itertools・・ですかね。
応用(3):複数のlistを連結してループ
例えば、以下のような2つのlistを考えます。
a = ['01','02','03']
b = ['04','05','06']
この2つを連結して、['01','02','03','04','05','06']のlistとしてループを回したい場合は、chainを使うと以下のようにできます。
import itertools as itr a = ['01','02','03'] b = ['04','05','06'] for x in itr.chain(a,b): print(x)
itertoolsのchainは単純に連結してくれるので、あたかも、['01','02','03','04','05','06']のように処理されます。
応用(4):複数のリストを並列にループ
a[0]とb[0]、a[1]とb[1]みたいに、2つのリストを並列に扱いたい場合もあります。
普通のやり方だと、こんな感じです。
a = ['01','02','03'] b = ['04','05','06'] for i in range(len(a)): print(a[i],":",b[i])
同じことをzip() を使って以下のようにも書けます。
a = ['01','02','03'] b = ['04','05','06'] for x,y in zip(a,b): print(x,":",y)
短さは同じですけど、zip()の方が若干スマートです。
ちなみに、zip()は2つのlistの長さが違う場合は、短い方の長さだけ処理します。
これを長い方に合わせたい場合は、「zip_longest」を使います。
その例です。
import itertools as itr c = ['a0','b0','c0','d0'] d = ['04','05','06'] for x,y in zip(c,d): print(x,":",y) for x,y in itr.zip_longest(c,d): print(x,":",y)
上のzip()=短い方にあわせるの結果は、こうです。
a0 : 04
b0 : 05
c0 : 06
下の方(zip_longest)の結果はこうです。
a0 : 04
b0 : 05
c0 : 06
d0 : None
応用(5):forループに対してelseを使う
Pythonってforループに対して、elseが使えます。
この「else」は、「ループでbreak文が実行されなければ処理を実行し、そうでなければ実行しない」という妙な動きをします。
その2つのケースの例です。
a = [1,2,3,4,5] for i in a: print("Loop",i) if(i > 4): break else: print("break文は実行されなかった") for i in a: print("Loop",i) else: print("break文は実行されなかった")
実行結果です。
上の方は「break」しているので、こうなります。
Loop 1
Loop 2
Loop 3
Loop 4
Loop 5
下の方は「break」文が実行されてないので、elseブロック内の処理も動いてます。
Loop 1
Loop 2
Loop 3
Loop 4
Loop 5
break文は実行されなかった
今のところ、このelseを使うようなケースにであったことがないので、どの程度有効なのかは、よくわかりませんが、一応、書いておきます。
以下の記事に続きます。
ではでは。