Pythonロボティクスコース レッスン 4
テーマ.1-3 Python の関数
プログラムを簡潔にまとめるために使われる「関数」について学ぼう
チャプター1
このレッスンで学ぶこと
このレッスンでは、プログラムを簡潔にまとめるために使われる「関数」について学習していきます。レッスンの最後では、Studuino:bitのブザーから曲を流すときに、そのキーの高さを自由に設定できる処理を関数としてまとめる課題に取り組みます。
チャプター2
Pythonの関数
実際に社会の中で使われているシステムは、数万行を超える量のコードでそのプログラムが書かれています。そのような大きなプログラムほど、これから説明する「関数」を使って、簡潔にコードが記述されています。簡潔なコードは誰が見ても理解できるように整理されているため、メンテナンスの点でもとても優れています。
関数(function)という言葉は、数学の世界でも出てきます。Pythonにおける関数も、数学の関数とほとんど同じです。数学で「y = f(x)
」という式で表される関数は、「x
」という変数で定義された計算式「f(x)
」 があり、x に何らかの数値を代入して計算すると、1つの結果「y
」 が得られるというものです。
例として、次の関数を考えてみましょう。
f(x) = 2x + 3
この関数では、変数「x
」に「1」を代入した場合は結果が「5」に、「2」を代入した場合は結果が「7」になります。
f(1) = 2×1 + 3 = 5
f(2) = 2×2 + 3 = 7
つまり、変数に何らかの値を与えると、それが処理されて、何らかの結果が得られるものが関数です。プログラムの世界では、関数に与える値を「引数」、関数を処理して得られた結果を「戻り値」や「返り値」と言います。ただし、プログラムでは数学とは違い、引数や戻り値のない関数も作成できます。
(参考)
例えばdef samurai()と書いた場合、samuraiという関数が宣言されたことになります。defはdefineが由来で、和訳すると「定義する」という意味です。
2. 1 Pythonの組み込み関数
Pythonにはあらかじめ用意されている関数があります。これらは「組み込み関数」といい、これまで何度か使ってきたprint()
やtype()
、int()
なども実は組み込み関数です。
これまでに使用してきた組み込み関数の一覧
関数名 | 引数 | 戻り値 | 動作 |
---|---|---|---|
print() | 数値や文字列などのデータ | なし | 引数として受け取ったデータを画面(ターミナル)に出力する。 |
int() | 数値または文字列のデータ | 整数のデータ | 整数ではないデータを引数として受け取り、整数型のデータに変換して返します。 |
float() | 数値または文字列のデータ | 浮動小数点数のデータ | 浮動小数点数ではないデータを引数として受け取り、浮動小数点数型のデータに変換して返します。 |
str() | 数値データ | 文字列のデータ | 数値データを引数として受け取り、文字列型のデータに変換して返します。 |
len() | 文字列などのデータ | データの長さ | 引数として受け取ったデータの長さ(文字列の場合は文字数)を返します。 |
Pythonの関数では、関数に与えるデータのことを引数、関数が処理して得られた結果のことを戻り値といいました。引数は1つの場合もあれば2つ以上、もしくはない場合もあります。戻り値も同様に、何らかの結果が得られる関数もあれば、print()
のように画面に表示するだけの関数もあります。
上記以外にもPythonには多くの組み込み関数が用意されています。その他の組み込み関数について知りたい場合は、次のPython公式ドキュメントを参照してください。ただし、少し内容が難しいため、他のレッスンを終えてから読むことをお勧めします。
2. 2 関数を定義する
関数は自分で定義することもできます。「def」というキーワードの後ろに関数名と「()」、「:(コロン)」を書き、「()」の中には関数が受け取る引数を定義します。また、変数と同様に関数も予約語を除いて自由に名前を付けることができます。
※Pythonで関数を定義するためには、def
というキーワードを使用します。その後に関数名と引数を記述します。
関数の中で行いたい処理はその次の行から書いていきますが、このとき、1つ気を付けなければならないことがあります。それは関数内のコードは先頭にインデント(空白文字)を付けるということです。インデントがない場合、Pythonは関数内のコードであることを認識できません。
インデントは通常「Tab」キーで入力できますが、4個の半角スペースでも同じくインデントとなります。ただし、全角の空白文字はインデントにならず、エラーの原因になりますので、注意してください。通常は4個の半角スペースで統一してください。
では練習として、 引数「x」を受け取り、「x」を2乗した結果を戻り値として返す関数「square」 を定義し、色々な数値を渡して結果を表示してみましょう。
※「square」は英語で「正方形」のほかに「2乗」を意味します。このように関数にはできるだけ、内部のコードを読まなくても、どのような振る舞いを行うのかが分かるような名前をつけるように心掛けてください。
コードはMuのエディタエリアに書いていきます。 まずは、名前をsquare
とし、引数x
を受け取る関数を定義します。
- def square(x):
次に関数内のコードを書きます。引数x
を2乗した結果を変数result
に代入します。インデント(半角スペース4個分)を忘れないように注意しましょう。
※「result」は英語で「結果」を意味します。
- def square(x):
- result = x**2
変数result
を戻り値として返します。関数から値を返すときは、「return文」を使います。次のように書きましょう。
- def square(x):
- result = x**2
- return result
これで関数が定義できました。画面上方の「実行」ボタンをクリックして、このプログラムを実行しましょう。
関数は定義して実行しただけでは何も結果は得られません。関数は呼び出して使う必要があります。ターミナルに次のコードを入力し、呼び出した関数square()
で「10の2乗」を計算してみましょう。
>>> square(10)
100
このように「関数名(引数)
」の形式で関数を呼び出すことができます。引数を他の値に変えても同じように2乗した結果が得られることを確認してみましょう。
- 「123の2乗」の計算
>>> square(123)
15129
- 「1.2の2乗」の計算
>>> square(1.2)
1.44
ここでは、2乗の計算を行う関数を定義しましたが、このくらいであれば関数を定義せずに演算子「 ** 」で直接計算しても良さそうです。しかし、何十行にも渡るコードで複雑な計算を行う場合はどうでしょうか。実行する度に毎回式を書くのはとても大変です。そんなとき、必要な引数だけを入力すると結果を返してくれる関数を用意しておくと、プログラムを簡潔にまとめることができます。
チャプター3
プログラムの動作を説明するためのコメント
変数や関数の名前は、それらがプログラムの中でのどのような役割をもつのかが分かるように付けることが大切だと学びました。ですが、名前だけではコードを読む人に十分な情報を提供できないこともあります。そのようなときは、より詳しい情報を「コメント」として残します。
3. 1 コメントの書き方
プログラムに文字列データでも変数名でもない「ただの文字」を記述すると、エラーになります。そのためPythonでは、先頭に「 # 」をつけてコメントを書くというきまりがあります。次の利用例を見てみましょう。(9、12行目のシングルクオーテーションを書き直してください)
- # コメントでは、日本語を使うこともできます。
- a = 10 # 変数に10を代入
- b = 20 # 変数に20を代入
- # 下のコードでは変数aを上書きしていますが、#でコメント化しているため実行されません。
- # a = 50
- c = a + b
- ‘ ‘ ‘
- このようにクォーテーションを3つ重ねた内側に記述することで、
- 複数行に渡るコメントを残すこともできます。
- ‘ ‘ ‘
- print(c)
このプログラムを実行すると、次のような結果になります。
>>>
raw REPL; CTRL-B to exit
>OK
30
途中でa = 50
と変数a
を上書きするコードがありましたが、その行をコメント化しているため、最初に定義したa = 10
で計算されて「30」が結果として表示されています。
このように、コメントはただのメモです。プログラムを処理する上では無視されます。「#」を使う場合は、この記号の後ろから行末までが全てコメントという扱いです。次の行の先頭からは普通にPythonのコードを記述できます。また、「#a = 50
」のように、特定の命令の行頭に#をつけることで、一旦保留にしておきたい処理を無効化することもできます。もしまた、再度その処理が必要になったときは、#を削除するだけで済むのでとても便利です。
また、9行目~12行目のように、3個連続したクォーテーション(「’’‘」や「”””」)囲みコメント化する仕組みを「ヒアドキュメント」といいます。長文になる説明や、複数行に渡りコードを無効化したい場合に使います。
コメントは、自分の作ったコードを他の人に見せるときや、以前に自分自身で作ったコードを忘れた頃に見返すときに、どういう意図でそのコードを記述したかを理解する助けになります。変数名の付け方とあわせて効果的に活用してください。
チャプター4
課題:Studuino:bitのブザーから鳴らす音を関数にまとめる
テーマ.1-2では、変数を利用してStuduino:bitのブザーから流れる曲のテンポを制御しました。ここでは、引数に「0~5」の6段階でキーの高さを指定することで、音域を変えて曲を流す関数を定義します。
4. 1 プログラムの作成
はじめに、Studuino:bitのブザーと時間の制御を行うための準備コードを書きます。以下のコードをコピーして、エディタエリアに貼り付けましょう。
- from pystubit.board import buzzer
- import time
次に、キーの高さを引数として、ブザーか曲を流す関数play_music(key)
を定義します。以下のように4行目にコードを追加しましょう。
- from pystubit.board import buzzer
- import time
- def play_music(key):
流す曲は「大きな古時計」です。関数play_music()
の中に、順番に音を鳴らすコードを追加します。以下の5行目~29行目のコードをコピーして貼り付けましょう。また、貼り付けた各コードの先頭にインデントがついていることを確認しましょう。(※このまま張り付けるとエラーとなります。各コードの先頭にインデントを設定してください)
【サンプルコード 4-1-1】
- from pystubit.board import buzzer
- import time
- def play_music(key):
- buzzer.on(str(55+key*12))
- time.sleep_ms(600)
- buzzer.on(str(60+key*12))
- time.sleep_ms(600)
- buzzer.on(str(59+key*12))
- time.sleep_ms(300)
- buzzer.on(str(60+key*12))
- time.sleep_ms(300)
- buzzer.on(str(62+key*12))
- time.sleep_ms(600)
- buzzer.on(str(60+key*12))
- time.sleep_ms(300)
- buzzer.on(str(62+key*12))
- time.sleep_ms(300)
- buzzer.on(str(64+key*12))
- time.sleep_ms(300)
- buzzer.on(str(64+key*12))
- time.sleep_ms(300)
- buzzer.on(str(65+key*12))
- time.sleep_ms(300)
- buzzer.on(str(64+key*12))
- time.sleep_ms(300)
- buzzer.on(str(57+key*12))
- time.sleep_ms(600)
- buzzer.off()
各高さの音を鳴らすコードは以下の形式で書いています。
buzzer.on(str(基準キーのMIDIノート番号 + 変数「key」*12))
buzzer
のon()
という命令で「()
」の中に指定する音の高さは、「オクターブ付きの音名」かもしくは、「MIDIと呼ばれる世界標準の規格で定められたノート番号」のどちらかで表します。ただし、指定するときはどちらも文字列にしておく必要があります。
MIDIノート番号表
オクターブ付きの音名(英語名) | 音名(日本語名) | MIDIノート番号 |
---|---|---|
C3 | ド3 | 48 |
D3 | レ3 | 50 |
E3 | ミ3 | 52 |
F3 | ファ3 | 53 |
G3 | ソ3 | 55 |
A3 | ラ3 | 57 |
B3 | シ3 | 59 |
C4 | ド4 | 60 |
D4 | レ4 | 62 |
E4 | ミ4 | 64 |
F4 | ファ4 | 65 |
G4 | ソ4 | 67 |
A4 | ラ4 | 69 |
B4 | シ4 | 71 |
C5 | ド5 | 72 |
1オクターブ高い音になると、MIDIノート番号は12ずつ増えます。例えば、C3とC4では、「60-48=12」となり、F3とF4でも「65-53=12」と同じ結果となります。
この性質を利用して、C3が含まれる1オクターブの範囲を基準として、そこから1オクターブ分キーが高くなる(変数key
が1増える)たびに、12ずつMIDIノート番号も増える計算式「50+key*12
」を立てています。MIDIノート番号で音の高さを指定するときも、文字列である必要があるため、計算結果を標準関数のstr()
で数値から文字列に変換しています。
4. 2 プログラムの実行
これで関数の定義ができました。画面上方の「実行」ボタンをクリックしてこのプログラムを実行しましょう。
実行したプログラムで定義された関数は、ターミナルから呼び出して実行することができました。以下のコードをターミナルに入力して、「Enter」キーで実行しましょう。
>>> play_music(0)
無事、曲が流れることが確認できたら、今度は引数に1~5の数字を順番に指定して実行し、段々と音域の高い所で曲が流れることを確認しましょう。
>>> play_music(1)
>>> play_music(2)
>>> play_music(3)
>>> play_music(4)
>>> play_music(5)
もし、このとき引数に6以上の数値や-1以下の整数値を指定するとエラーが起きます。これは、「50+key*12
」の計算結果がStuduino:bitのブザーから鳴らせるMIDIノート番号の範囲「48~127」の外にあるためです。
チャプター5
おわりに
5. 1 このレッスンのまとめ
本レッスンでは、Pythonの「関数」と「コメント」について学びました。関数には、ここでは紹介ができなかった便利な機能や使い方が他にもあります。これらについては、学習を続けていく中で少しずつ説明をしていきます。今はまず、このレッスンを通して学習した関数の使い方をしっかりとおさえておきましょう。
5. 2 次回のレッスンについて
次回のレッスンでは、Pythonをはじめとする「オブジェクト指向」と言われるプログラミング言語の中心となる「オブジェクト」について、その基本を学習します。