HELLO CYBERNETICS

深層学習、機械学習、強化学習、信号処理、制御工学、量子計算などをテーマに扱っていきます

【Python】最低限抑えておきたいループの書き方

 

 

follow us in feedly

https://cdn.blog.st-hatena.com/images/theme/og-image-1500.png

はじめに

プログラミングというのは同じことを実現するにしても色々な書き方があります。 ではそれらすべての書き方を網羅していなければならないかと言われるとそうでもなく、むしろ同じ処理の書き方が何通りもあるのならば、 「効率の良い、読みやすい書き方」を1つ覚えておくことが重要だと思われます。

今回は初心者が抑えておくと良いループの書き方を列挙しておきます。

while文

while文での基本的なループの書き方

while文では繰り返し回数を保存しておくcount変数を以下のように初期化しておき、ループの中でcount += 1として繰り返し回数を記録しておく方法が一般的です。 while文では while 条件式のときに条件式=Trueの場合に繰り返しを続行します。したがって、5回ループを行いたい場合は以下のようなコードになるでしょう。

count = 0
while count < 5:
    print(count)
    count += 1
# 0
# 1
# 2
# 3
# 4

while文をbreakで止める

一方で、while True:によってループ式を書くことで、ループを常に回し続けるということができます。 意図してない時にこれをやってしまうと大変なことになるのですが、ループ内でbreakを実行することでループを抜けることができます。 これを利用して上記と同じ処理を下記のコードでも実行できます。

count = 0
while True:
    if count >= 5:
        break
    print(count)
    count += 1
# 0
# 1
# 2
# 3
# 4

若干コードは長くなってしまいましたが、while 条件式と書く場合に、条件式がやけに複雑になってしまったりする場合はこのような書き方をしてもいいでしょう。 ループの中でどういう時にループを終了するのかが明記されており、可読性が高いと感じるシーンもあるはずです。

continueで1回ループをスキップする

continueを使うと、それが呼び出された時点で次のループに移行します。具体例を見たほうが早いでしょう。

count = 0
while True:
    if count >= 5:
        break
    
    if count == 3:
        count += 1 
        continue
    
    print(count)
    count += 1
# 0
# 1
# 2
# 4

こちらではif count==3のときにはcount += 1としてからcontinueが呼びだされております。この時点その下にある処理は全てスキップされ、次のループに移行します。 したがってprint(count)が表示されることはなく、結果として出力に3が現れることがなくなったのです。

ループが最後まで到達して終了したときにのみ処理を行う

ループが最後まで到達して終了した時にのみ実行される処理を書きたい場合は、while else文が使えます。下記のように書くと、whileが最後まで到達して終了するため、else以降のコードが実行されています。

count = 0

while count < 5:
    print(count)
    count += 1
else:
    print("finish")
# 0
# 1
# 2
# 3
# 4
# finish

一方で下記のコードの場合else以降のコードは実行されません。

count = 0

while count < 5:
    if count == 2:
        break
    print(count)
    count += 1
else:
    print("finish")
# 0
# 1

なぜならこのループはbreakによってループが終了されており、これは「whileが最後まで到達して終了した」というわけではないためです。

これらを駆使すれば、基本的なループに関する処理を書くことはできるでしょう。

for文

for文での基本的なループの書き方

for文を使う場合の基本的なループの書き方は下記のようになります。

for i in range(5):
    print(i)
# 0
# 1
# 2
# 3
# 4

range(5)によって5回ループを繰り返すということを実現できます。 for i in range(5):というコードでは、最初はi=0としてループを実行し、次のループではi=1でループを実行し、これをi=4となるまで繰り返します。 したがってprint(i)によって数字を表示することができているのです。

for文の基本はfor 変数 in イテレータ:

さて、while文に比べてfor文の方は少し複雑です。単にループを繰り返すというわけではなく、for 変数 in イテレータという形でイテレータから順次変数に値を代入して、処理を実行していきます。 そして、イテレータの最後の要素に到達した時にループが終了します。ここでイテレータというのは、データがたくさん入っていて、それが順序付けられているものくらいに思っておいてください。

例えばstr型はイテレータです。

for i in "abcde":
    print(i)
# a
# b
# c
# d
# e

また、リストもイテレータです。for文を書く上では非常に相性の良い存在です。

for word in ["Hello", "Cybernetics", "Thank", "you"]:
    print(word)
# Hello
# Cybernetics
# Thank
# you

再び基本のforループへ

最初に見たfor i in range(5)range(5)もイテレータというわけです。このrange()関数はもっと柔軟に活用することができ、例えば2~4を格納したイテレータを作りたければ

for i in range(2, 5):
    print(i)
# 2
# 3
# 4

とすることができますし、1〜9の値を1個飛ばしで格納したイテレータを作りたければ

for i in range(1, 10, 2):
    print(i)
# 1
# 3
# 5
# 7
# 9

と書くことができます。

要素の番号と要素をセットで取り出したいenumerate()関数

さて、ここでPythonを始めたばかりの時に僕が書いていたコードを紹介します。 このときrange(N)はfor文をN回繰り返すために使うものだな!くらいの感覚しかなかったため、以下のようなコードを書いてしまっていました。

greeting = ["Hello", "Cybernetics", "Thank", "you"]
N = len(greeting)
for i in range(N):
    print(i, greeting[i])
# 0 Hello
# 1 Cybernetics
# 2 Thank
# 3 you

今回はわかりやすさのために文章を入れていますが、例えばデータを取り出していきながら、「i番目のデータは●●です」みたいなことを示したいケースにこのようなコードを用いていました。 これをもっと簡潔に表すことのできるenumerate()関数を使いましょう。

greeting = ["Hello", "Cybernetics", "Thank", "you"]
for i, word in enumerate(greeting):
    print(i, word)
# 0 Hello
# 1 Cybernetics
# 2 Thank
# 3 you

このコードでは、enumerate()で包んであげることで、greetingの要素をwordに、そのインデックスをiに格納してprint(i, word)を実行します。 先ほどのコードではiだとかNだとか変数が無駄に色んな所に現れてしまい、もっと複雑なことをやろうとすると後々見なおした時に「なんの変数だっけ?」となってしまいます。 enumerateを知っている人ならば、上記のコードを見れば何をやっているのか一目瞭然になるので、是非とも覚えておきたいテクニックです。

2つのリストから順次同時に取り出す

要素とインデックスを同時に取り出すenumerateが便利なのはよくわかりました。 更にもっと便利なzip()関数を紹介しましょう。

main_dishes = ["fish", "beef", "pork"]
drinks = ["coffee", "tea", "milk"]
for main_dish, drink in zip(main_dishes, drinks):
    print(main_dish, drink)
# fish coffee
# beef tea
# pork milk

こいつは2つのリストを渡してやることで、それぞれのリストから1つずつ要素を取ってくるfor文を実現できます(2つのリストの各要素をタプルで取り出してくれます)。 実は渡すリストは3個でも4個でももっと多くて構いません!

辞書のkeyとvalueを取り出す

最後に、辞書型をforループで扱うときに出てくる最も基本的なものを覚えておきましょう。

d = {"x": 100, "y": 200, "z": 300}
for k, v in d.items():
    print(k, ":", v)
# x : 100
# y : 200
# z : 300

肝はd.items()の部分ですが、これによってkeyとvalueのタプルをイテレータの形で返してくれるため、for文に突っ込むことができるというわけです。 小難しいことはともかくとして、よく使うコードなので是非とも覚えておきましょう。