タイトルに「ループの流れを変える」とありますが、ループの流れを変えるって、どういうことなのですか?
途中で中止してみたり、最後に動きを追加したり・・・
なんだか面白そうですね!
ループと組み合わせて使う文
今回解説するのは、以下の3つの文だ。これらをループと組み合わせて使うことで、ループの流れを変えることができるのだ。
文 | 流れ |
break | ループ処理の途中でループから抜け出す。 |
else | ループ処理完了後に動作を追加する。 |
continue | ループ処理の途中でループの先頭に戻る。 |
Pythonでは、ループを作るのに「for」文、「while」文の2つを使うが、「break」文、「else」文および「continue」文は、どちらのループでも使うことができるのだ。
なんだか抽象的で、ピンとこないのですが・・・
では、実際のプログラムで確認してみよう。マイクロビットで時計の針を1回転させるプログラムを改造してみるよ。
時計の針のプログラム(これまでの復習)
これが、「配列の要素とインデックス」の時に作った時計の針のプログラムですね。
プログラム1
- 1行目 from microbit import *
- 2行目 hari = [Image.CLOCK1, Image.CLOCK2, Image.CLOCK3, Image.CLOCK4, Image.CLOCK5, Image.CLOCK6, Image.CLOCK7, Image.CLOCK8, Image.CLOCK9, Image.CLOCK10, Image.CLOCK11, Image.CLOCK12]
- 3行目
- 4行目 def Clock():
- 5行目 a = 0
- 6行目 while a < 12:
- 7行目 display.show(hari[a])
- 8行目 sleep(100)
- 9行目 a = a + 1
- 10行目
- 11行目 while True:
- 12行目 if button_a.get_presses():
- 13行目 Clock()
マイクロビットのAボタンが押されると、LED表示部分で時計の針が一回転するのだ。(詳しくは、以下をご覧ください。新しいタブで開きます。)
ループを「for」文で作ると、もう少しシンプルになるのでしたね。
プログラム2
- 1行目 from microbit import *
- 2行目 hari = [Image.CLOCK1, Image.CLOCK2, Image.CLOCK3, Image.CLOCK4, Image.CLOCK5, Image.CLOCK6, Image.CLOCK7, Image.CLOCK8, Image.CLOCK9, Image.CLOCK10, Image.CLOCK11, Image.CLOCK12]
- 3行目
- 4行目 def Clock():
- 5行目 for b in hari:
- 6行目 display.show(b)
- 7行目 sleep(100)
- 8行目
- 9行目 while True:
- 10行目 if button_a.get_presses():
- 11行目 Clock()
どちらのプログラムも同じ動きをするのだ。(「for」文については、以下をご覧ください。新しいタブで開きます。)
【マイクロビット入門】(15)「for」ループで配列を扱おう。
「break」文でループを中断する。
初めに解説するのは、「break」文だ。
これは前にも出てきたやつですね?ループから抜け出すときに使う文でしたっけ?
よく覚えていたね、その通りだ。ループの対象となるブロックの中に「break」文を入れておけば、そこでループから抜け出すことができる。
「if」文と組み合わせて、ボタンが押されたときにループから抜け出すのに使ったりしていましたね。
プログラム3(関数Clock()を抽出)
- 4行目 def Clock():
- 5行目 a = 0
- 6行目 while a < 12:
- 7行目 display.show(hari[a])
- 8行目 sleep(100)
- 9行目 a = a + 1
- 10行目 if button_b.get_presses():
- 11行目 break
時計の針が動いている間にBボタンが押されると、10行目の「break」文によってループから抜け出すのだ。
「for」文の場合はどうなるのですか?
次のようにすればよいのだ。
プログラム4(関数Clock()を抽出)
- 4行目 def Clock():
- 5行目 for b in hari:
- 6行目 display.show(b)
- 7行目 sleep(100)
- 8行目 if button_b.get_presses():
- 9行目 break
「while」文の時と同じですね。ちなみに飛行機のプロペラの時にも「break」文を使っています。参考にしてネ。(新しいタブで開きます。)
【マイクロビット応用】[2] プラモの飛行機のプロペラ(1)
「else」文でループの終わりに動作を追加する。
次は「else」文について解説するのだ。
これも見覚えがありますよ。・・・あれ、「else」文は「if」文と一緒に使うのでは?
ウム。「if」文と一緒に使うこともできる。入出力端子について調べたときに出てきたね。(以下をご覧ください。新しいタブで開きます。)
【マイクロビット入門】(10)マイクロビットの機能を使ってみよう。
そして、「for」文、「while」文と一緒に使った場合は、ループによる繰り返しがすべて行われた後の動きを追加することができるのだ。例えばこんな感じだ。
プログラム5(関数Clock()を抽出)
- 4行目 def Clock():
- 5行目 a = 0
- 6行目 while a < 12:
- 7行目 display.show(hari[a])
- 8行目 sleep(100)
- 9行目 a = a + 1
- 10行目 if button_b.get_presses():
- 11行目 break
- 12行目 else:
- 13行目 display.show(Image.HAPPY)
マイクロビットに書き込んで、実行してみると・・・時計の針が1回転した後、「Happy」のイメージが表示されましたね!
針が回っている途中でBボタンを押すとどうなるかな?
針が動いている途中で、Bボタンを押すと・・・今度は「Happy」が表示されませんね。
「else」文の後に続くブロックは、ループが完了した時だけ実行される。「break」文で中断された場合は実行されないので、注意が必要だ。
この「else」文も「for」文と一緒に使えるのですね?
その通りなのだ。プログラム6のループを「for」文に置き換えると、次のようになるのだ。
プログラム6(関数Clock()を抽出)
- 4行目 def Clock():
- 5行目 for b in hari:
- 6行目 display.show(b)
- 7行目 sleep(100)
- 8行目 if button_b.get_presses():
- 9行目 break
- 10行目 else:
- 11行目 display.show(Image.HAPPY)
マイクロビットで動かしてみると・・・「while」の場合と同じように動きますね。
「continue」文でループの途中で先頭に戻る。
次は「continue」文ですね。これは初めて見るやつですね。「ループの途中で先頭に戻る」とありますが・・・
では、具体例で見てみよう。これまでと違って、「while」文と「for」文で異なる点が出てくるので、分けてみてみよう。
「while」文の場合
「while」文の場合から見ていこう。プログラム1の関数「Clock()」に「continue」文を追加してみたのだ。
プログラム7(関数Clock()を抽出)
- 4行目 def Clock():
- 5行目 a = 0
- 6行目 while a < 12:
- 7行目 if hari[a] == Image.CLOCK3:
- 8行目 continue
- 9行目 display.show(hari[a])
- 10行目 sleep(100)
- 11行目 a = a + 1
マイクロビットで実行してみると・・・あれ、針が2時のところから動かなくなってしまいましたよ。・・・もう、aボタンにも反応しませんね。
ループが実行されて変数「a」の値が増えていき、2になると「hari[a]」の値は「Image.CLOCK3」となるのは分かるね?
変数「a」が配列「hari」のインデックスとして使われていて、「a」が2ということは、配列「hari」の先頭から3番目の要素を使用する、ということですね。
「hari[a]」の値が「Image.CLOCK3」になると、7行目の「if」文が成立し、8行目の「continue」によってループの先頭に戻る、というようにプログラムが動くのだ。
ループの先頭、ということは、6行目に戻るのですね。
- 6行目 while a < 12:
- 7行目 if hari[a] == Image.CLOCK3:
- 8行目 continue
- 9行目 display.show(hari[a])
- 10行目 sleep(100)
- 11行目 a = a + 1
「continue」文によってループの先頭に戻ってしまうので、9行目、10行目、11行目は実行されない。すると・・・
11行目が実行されないということは、インデックスの変数「a」が2のまま変わらなくなってしまう、ということですか?
よく気がついたね!変数「a」が2のままなので、6行目の条件「a < 12」が成立し続け、無限ループになってしまうのだョ。
へぇ~、では、どうすれば無限ループから抜けられるのですか?
「continue」文の前で変数「a」の値を増やせばよい。例えば1増やせば、3時のイメージをとばして表示され、ループが完了ずるのだ。
プログラム8(関数Clock()を抽出)
- 4行目 def Clock():
- 5行目 a = 0
- 6行目 while a < 12:
- 7行目 if hari[a] == Image.CLOCK3:
- 8行目 a = a + 1
- 9行目 continue
- 10行目 display.show(hari[a])
- 11行目 sleep(100)
- 12行目 a = a + 1
マイクロビットでこのプログラムを動かすと・・・3時がとばされて針が回りましたね。
「for」文の場合
「for」文の場合はどうなるのですか?なんか、異なる点があるみたいですけど・・・
さっそくやってみよう。プログラム2の関数「Clock()」に「continue」文を追加してみよう。
プログラム9(関数Clock()を抽出)
- 4行目 def Clock():
- 5行目 for b in hari:
- 6行目 if b == Image.CLOCK3:
- 7行目 continue
- 8行目 display.show(b)
- 9行目 sleep(100)
マイクロビットで実行してみると・・・あれ、今度は無限ループにならずに終了しましたね!しかも、3時の針をとばして一回転しましたよ。
ループの先頭の5行目が「for」文で記述されているのがポイントだ。
と、いいますと・・・
「for」文は、実行されるたびに指定された変数に、指定された配列の前から順に要素をコピーするのだ。
これは、前回やりましたね。
今回のプログラムの場合だと、変数「b」の値が「Image.CLOCK3」となると、6行目の「if」が成立して、7行目の「continue」で5行目に戻る。
- 5行目 for b in hari:
- 6行目 if b == Image.CLOCK3:
- 7行目 continue
- 8行目 display.show(b)
- 9行目 sleep(100)
フムフム。
5行目は「for」文なので、変数「b」に配列「hari」の、次の要素、つまり「Image.CLOCK4」が格納されるのだ。そうすると、どうなるかな?
ええと、5行目の次は6行目で・・・変数「b」が「Image.CLOCK4」だから、6行目の「if」文が成立しなくなる!だから、無限ループに陥らずに済むんだ!
「while」文と「for」文の動きの違いがこの結果につながっている。「for」文はループするときに、配列の各要素を取り出してくる動作が伴っている点が、「while」文と異なるのだ。
この違いを理解して、ループを使いこなしてほしいのだ。
ガンバリマス!
まとめ
今回のまとめデ~ス!
- 「break」文によって、ループ処理の途中でループから抜け出すことができる。
- ループと「else」を組み合わせることで、ループ処理完了後に動作を追加できる。
- 「continue」文によって、ループ処理の途中でループの先頭に戻ることができる。
ループの流れを変化させて、マイクロビットに面白い動きを組み込んでみてネ!
またね~~♩
コメント