【マイクロビット入門】(11)グローバル変数とローカル変数

マイクロビット

 「グローバル変数」とか「ローカル変数」という名前がついている、ということは、変数にも種類があるということですか?

 ウム、その通りだ。ある「関数」の内部だけで有効なのが「ローカル変数」、プログラム全体で有効なのが「グローバル変数」ということなのだが・・・

 何を言っているのか、全く分かりまセーン!

 やはりそうなるネ。では、詳しく説明しよう。

ある関数の内部だけで有効な「ローカル変数」

 では、初めに「ローカル変数」について説明しよう。先ほど「ローカル変数は関数の内部だけで有効」と説明したが、「関数」については覚えているかな?

 「def」文で名前を決めて、「def」文に続くブロックで中身を書くのでしたね?

 ウム、その通りだ。関数の内部とは、ここでいう関数の中身、すなわち「def」文に続くブロックのことなのだ。(忘れてしまった人は以下を見てね。新しいタブで開きます。)

【マイクロビット入門】(8)関数を作ってみよう。

 そして、関数の中身を表すブロック内で定義された変数が「ローカル変数」ということなのだよ。

ローカル変数の作り方

 「ローカル変数」はどうやって作るのですか?

 簡単な実例を使って説明しよう。例えば下のようなプログラムを考えてみる。

  • 行目 from microbit import *
  • 2行目
  • 3行目 def test_a():
  • 4行目  a = 1
  • 5行目  display.scroll(a)
  • 6行目
  • 7行目 while True:
  • 8行目  if button_a.get_presses():
  • 9行目   test_a()

 「a」ボタンを押すと、関数「test_a」が呼び出されるプログラムですね?

 その通りだ。そして、このプログラムの4行目では、変数「a」に1を入れることで、変数「a」を用意している。これを、「変数aを定義する。」というように表現する。

 変数「a」に1を入れるので、次の5行目によってマイクロビットの表示部分に1が表示されるのですね。

 ここで重要なのは、4行目が「インデント」されている、ということなのだ。

  • 3行目 def test_a():
  • 4行目  a = 1
  • 5行目  display.scroll(a)

 確かに!ということは、4行目は関数「test_a」の内部ということになりますね!!

 イエース!これ、すなわち・・・

 変数「a」は、ローカル変数!・・・ってことですね!

 ・・と、いうことなのだ!

「ローカル変数が関数の内部だけで有効」とは?

 でも、「ローカル変数が関数の内部だけで有効」というのはどういうことですか?

 これを説明するために、プログラムを次のように改造してみよう。

  • 行目 from microbit import *
  • 2行目
  • 3行目 def test_a():
  • 4行目  a = 1
  • 5行目  display.scroll(a)
  • 6行目
  • 7行目 while True:
  • 8行目  if button_a.get_presses():
  • 9行目   test_a()
  • 10行目   display.scroll(a)

 10行目に変数「a」の中身を表示する文を追加してみたのだ。マイクロビットで実行するとどうなるかな?

 パイソンエディターの「Flash」ボタンでマイクロビットに書き込んで、マイクロビットのAボタンを押すと・・・あれ、エラーになっちゃった!

 今回のプログラムでは、関数「test_a」の中身は4行目と5行目の2行というのは分かるかな?

 はい。ということは、10行目は関数「test_a」の外なので、変数「a」は有効ではない、ということですか?

 よく分かったね。その通りなのだ。そして、10行目で有効ではない変数「a」を表示しようとしたので、エラーとなってしまった、という訳なのさ。

 そういうことなのかぁ。

プログラム全体で有効なグローバル変数

 ところで、最初に「プログラム全体で有効なのがグローバル変数」と言っていましたね?

 ウム。確かにそんなことを言ったような気がするが・・・(嫌な予感がするぞ)

 ということは、変数「a」を「グローバル変数」にすれば、さっきのプログラムの10行目はエラーにならない、ということですか?

 おぉ、そこに気が付いたのか!なかなか鋭いね。(セーフなのだ)

 でも、どうやったら変数「a」が「グローバル変数」になるのですか?

グローバル変数の作り方

 「ローカル変数」は、「関数」の内部で変数を定義(変数を用意して初期値を入れる)したね。

 そうでした。さっきやりましたね。

 「グローバル変数」は、「関数」の外で変数を定義すればよいのだ。先ほどの例で考えると、次のようになる。

  • 行目 from microbit import *
  • 2行目
  • 行目 a = 1
  • 4行目
  • 5行目 def test_a():
  • 6行目  display.scroll(a)
  • 7行目
  • 8行目 while True:
  • 9行目  if button_a.get_presses():
  • 10行目   test_a()
  • 11行目   display.scroll(a)

 関数「test_a」の中にあった「a = 1」が3行目に移動しましたね。インデントもなくなっている。

 すなわち、変数「a」は関数の外で定義され、「グローバル変数」になったのだ。

 マイクロビットにプログラムを書き込んで、Aボタンを押すと・・・1が二回表示されましたね!

 変数「a」は、「グローバル変数」なので、11行目でも有効に使える、ということなのだ。

 6行目の「display.scroll(a)」で1回表示されて、11行目のdisplay.scroll(a)」でもう1回表示されたのですね。

関数内でグローバル変数の値を変えるには?

 ところで赤トマト君、関数「test_a」の中でグローバル変数「a」の値を変更するには、どうすればよいと思うかい?

 う~ん、と言いますと?

 例えば、関数「test_a」の中でグローバル変数「a」を1増やすことで、Aボタンが押された回数を表示するようにプログラムを改造するには、どうする?

 こんなふうにプログラムを改造してみてはどうでしょうか?

  • 行目 from microbit import *
  • 2行目
  • 3行目 a = 0
  • 4行目
  • 5行目 def test_a():
  • 6行目  a = a + 1
  • 7行目  display.scroll(a)
  • 8行目
  • 9行目 while True:
  • 10行目  if button_a.get_presses():
  • 11行目   test_a()

 3行目でグローバル変数「a」に0を入れて置きます。Aボタンが押されると、5行目の関数「test_a」が呼び出されて、6行目で「a」が1増えて、7行目で表示されます。

 おぉ、頑張ったね!では、動かしてごらん。

 了解です!・・・あれ、6行目でネームエラーになってしまいましたね。

 実は、6行目は、「ローカル変数aを用意して、a+1を格納する」という意味になってしまうのだ。

  • 5行目 def test_a():
  • 6行目  a = a + 1
  • 7行目  display.scroll(a)

 なんですって!

 関数の内部で変数に値を代入するのは、ローカル変数の定義を行う、と解釈されてしまうのだ。

 確かに、ローカル変数の定義の書き方と同じですね。

 そして、ローカル変数「a」の宣言に「a」を使おうとしたので、ネームエラーになってしまったという訳なのョ。

 では、関数の内部でグローバル変数の値を変えるには、どうすればよいのですか?

 その場合は、「global」文を使って、あらかじめ変数「a」がグローバル変数であることを明記すればよい。

  • 5行目 def test_a():
  • 6行目  global a
  • 7行目  a = a + 1
  • 8行目  display.scroll(a)

 では、マイクロビットで動かしてみます。「Flash」ボタンで書き込んで・・・おぉ、確かにエラーにならなくなりました!Aボタンを押した回数が表示されるようになりましたよ!

今回のまとめ

 今回説明した「グローバル変数」と「ローカル変数」の違いを以下にまとめてみたョ。

  1. ローカル変数は関数の内部のみで有効。
  2. グローバル変数はプログラム全体で有効。
  3. ローカル変数内でグローバル変数の値を変更する場合は「global」文を用いる。

 またね~

コメント

タイトルとURLをコピーしました