SE_BOKUのまとめノート的ブログ

SE_BOKUが知ってること・勉強したこと・考えたことetc

Python3の「Forループ」の基本と応用技など/Python文法

f:id:arakan_no_boku:20181124131221j:plain

目次

Python3の「Forループ」の基本と応用技など

今回は、Pythonのforループの書き方を整理します。

整数のカウントアップ・ダウン( range)

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()」は、整数専用で、浮動小数点数は使えません。 

少数のカウントアップ・ダウン (numpy.arange())

少数の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までの繰り返しになります。  

listをループで処理(in) 
a = ['a','b','c','d','e','f','g']
    
for x in a:
    print(x)

inだけです。

'a'、'b'などの値が順に変数(x)にはいってくる感じです。

listをループで処理(enumerate) 

今度は値だけでなく、添え字も一緒に欲しい場合です。

a = ['a','b','c','d','e','f','g']
    
for i,name in enumerate(a):
    print(i,":",name)

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))よりスマートなので、自分はこちらを愛用してます。

ネストしたループ 

例えば、以下のように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)

 

ネストしたループをスマートに書く( 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・・ですかね。  

複数の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']のように処理されます。 

複数のリストを並列にループ(range版)

 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版)

同じことを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

forループに対してelseを使う 

Pythonってforループに対して、elseが使えます。

その例です。

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を使うようなケースにであったことがありません。

以下の記事に続きます。

arakan-pgm-ai.hatenablog.com

ではでは。