今回は「for」文によるループで「配列」を扱ってみるぞ。
前回言っていたやつですね。さっそく教えてください!
「for」文とは?
「for」文は、配列のすべての要素を個別に扱うループを作るための文なのだ。
- for [変数名] in [配列名]:
- 配列の要素の数だけ繰り返す。
- 繰り返されるのは、for文の後のブロック
- 配列の各要素が先頭から順に変数にコピーされる。
(「ブロック」は、インデントされた文の集まりのことです。詳しくは以下を見てね。(新しいタブで開きます。)
「変数名」と「配列名」というのが出てくるのですが、どういうことなのでしょうか?
「配列名」というのは、「for」ループの対象となる配列の名前なのだ。ここに対象の配列名を書けばよいのだ。
コレは何となく想像していました。
そして、「変数名」で指定された変数には、配列の各要素が先頭から順にコピーされるのだ。
な、な、な、何を言われているのか、全くわかりませ~ン!
具体例で説明した方が良さそうだね。前回作ったプログラムのループ部分を「for」文で書き換えてみよう。まずは、前回作ったプログラムを思い出してみるよ。
前回作ったプログラム
前回は、「while」ループを使って配列「hari」に格納された時計の針のイメージを順番に表示するプログラムを作成した。
これがその全文ですね。マイクロビットのAボタンが押されると、LED表示部分で時計の針が一回転するのでしたね。
プログラム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()
2行目で配列「hari」に時計の針の1時から12時までのイメージが格納される。そして、12行目でAボタンが押されたことを判定し、4行目~9行目の関数「Clock()」が呼び出されるのだ。
関数「Clock()」では、6行目がループの「while」文で、7行目~9行目のブロックで配列「hari」に格納された時計の針のイメージが順に表示されるのでしたね。
このプログラムの4行目~9行目を改造してみよう。
「for」文で時計を動かしてみよう。
先ほど説明したが、「for」文を作るには、「配列名」と「変数名」を指定しないといけない。
- for [変数名] in [配列名]:
先ほどのプログラムを改造する場合は、「配列名」は「hari」でいいのですか?
イエ~ス、その通りなのだ。
では、「変数名」は?5行目に「a」という変数がありますが、もしかしてこの「a」ですか?
残念ながら「a」ではない。変数「a」は、配列「hari」の何番目の要素を扱うのかを表すインデックスなのだ。
そ、そうでした。でも、他に変数はないような・・・
ここで指定する変数名は、まだ使われていない新しいものを使用する。例えば「b」としてみよう。そうすると、6行目は・・・
- 4行目 def Clock():
- 5行目 a = 0
- 6行目 for b in hari:
となるのだ。次は、「for」文に続くブロック(7行目~9行目)を改造するのだ。
いったい、どうなってしまうのですか?
こうなるのだ!
プログラム2(関数「Clockのみ」)
- 4行目 def Clock():
- 5行目 # a = 0
- 6行目 for b in hari:
- 7行目 display.show(b)
- 8行目 sleep(100)
- 9行目 # a = a + 1
7行目の「display.show()」に渡す変数が「hari[a]」から「b」に変わりましたね?
ウム。「for」文の変数「b」で、配列「hari」の要素を前から順にコピーされる。すると、変数「b」の中身は、ループが回るにつれて、以下のように変化するのだ。
ループ回数 | 変数「b」の中身 |
1回目 | hari[0] |
2回目 | hari[1] |
3回目 | hari[2] |
4回目 | hari[3] |
5回目 | hari[4] |
6回目 | hari[5] |
ループ回数 | 変数「b」の中身 |
7回目 | hari[6] |
8回目 | hari[7] |
9回目 | hari[8] |
10回目 | hari[9] |
11回目 | hari[10] |
12回目 | hari[11] |
配列のインデックスが0から始まることに注意してくれたまえ。
ループが回るごとに、変数「b」の中身が変わっていくのですね。ループの13回目以降はどうなるのですか?
今回作成した配列は要素が12個格納されている。従って、ループは12回実行されたら終了するのだ。
なるほど。ということは、「for」文では、配列を指定すれば、ループの回数は自動的に決まる、ということですね!
配列にいくつ要素が入っているかを気にしなくてもよいのが、「for」文のメリットなのだ。
ところで、5行目と9行目がコメントアウトされていますが・・・
- 4行目 def Clock():
- 5行目 # a = 0
- 6行目 for b in hari:
- 7行目 display.show(b)
- 8行目 sleep(100)
- 9行目 # a = a + 1
7行目の「hari[a]」が「b」に置き換わるので、インデックスとして用意した変数「a」が不要となる。そのため、5行目と9行目も不要となるのでコメントアウトしたのだ。
コメントアウトした部分を削除して全文を掲載してみます。
プログラム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()
関数「Clock()」が随分シンプルになりましたね!
「while」文のメリットはないのか?
ループで配列を扱う場合は「for」文を使う方が良さそうですね。プログラムがシンプルになりますし。
そうだね。配列の要素を前から順番に取り出して使う場合は「for」文が良いね。
「for」文ではない方がいい場合もあるのですか?
例えば配列を後ろから順番に使いたい場合は「for」文は使えず、「while」文を使う必要があるのだ。
配列を後ろから使いたいことなんて、あるのですか?
今回のプログラムを例に考えてみよう。時計の針を反対周りに動かしたい場合はどうかな?
確かに!後ろから表示すると、反対周りに動きそうですね。
さっそく試してみよう。プログラム2に、Bボタンを押すと針が反対周りに回る機能を追加してみたのだ。
プログラム3
- 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行目 def CounterClock():
- 10行目 a = 11
- 11行目 while a >=0:
- 12行目 display.show(hari[a])
- 13行目 sleep(100)
- 14行目 a = a – 1
- 15行目 display.show(hari[11])
- 16行目
- 17行目 while True:
- 18行目 if button_a.get_presses():
- 19行目 Clock()
- 20行目 if button_b.get_presses():
- 21行目 CounterClock()
9行目~15行目に「CounterClock()」という関数を追加したのだ。配列「hari」の要素を指定するために、10行目で変数「a」を用意している。
11行目~15行目が「while」ループですね。変数「a」が0以上の場合にループする、ということなのですか?「a」が0以上だと、ずーっと回り続けるのでは???
まず10行目を見てみよう。変数「a」には、最初に11が格納される。
フムフム。
そして、14行目で変数「a」に格納された値を1減らしている。つまり、ループが回るごとに変数「a」の値は減っていくのだ。
- 9行目 def CounterClock():
- 10行目 a = 11
- 11行目 while a >=0:
- 12行目 display.show(hari[a])
- 13行目 sleep(100)
- 14行目 a = a – 1
- 15行目 display.show(hari[11])
と、いうことは・・・そうか!変数「a」の値が11から徐々に減って、マイナスになったらループから抜ける、という訳ですね!
正解デス!そして、変数「a」は11から徐々に減っていくので、配列「hari」の要素が後ろから表示されるのだ。
すると、針の位置が12時のイメージから始まって、11時、10時と表示され、時計が反対に回るのですね。
このように、「for」文や「while」文も、作りたいプログラムに応じて使い分ければよいのデ~ス!
ところで、15行目は何のためにあるのですか?
- 15行目 display.show(hari[11])
配列「hari」の最初の要素は、時計の針が1時を指しているイメージなのだ。なので、15行目がないと、逆回転した後、1時の位置で針が止まってしまう。
これだと、ちょっと見栄えが良くないですね。
見栄えを良くするために、最後に12時のイメージを表示するようにした、ということなのだ。
マイクロビットで動かしてみると・・・ちゃんとBボタンで逆回転しますね。
まとめ
今回のまとめデ~ス
- 「for」文により、配列の各要素を前から順番に扱うプログラムをシンプルに作ることができる。
- 「for」文を使う場合は、インデックスの変数が不要となる。
- 作りたいプログラムに応じて「for」文と「while」文を使い分けよう。
次回もお楽しみに!
コメント