[Python入門]関数の基本:Python入門(2/2 ページ)
「関数とは」「関数呼び出しの方法」「組み込み関数」「ユーザー定義関数」「関数定義の方法」など、Pythonの関数の基本知識を説明する。
値を返す関数
関数から値を返すには「return文」を使用する。構文は次の通りだ。
return 戻り値
「戻り値」の部分には何らかの値(式)を記述する。変数でも構わないし、計算式でも構わない。ここでは簡単な例として「引数を取らず、常に整数値42を返す関数」を定義してみよう。
def get_ans4ultimateQ():
return 42
この関数は常に「42」を返すので、「return」の後にはそのまま「42」を置いているが、実際には何らかの計算や処理をした結果を返すのが一般的だ。また、return文によりその関数は実行を終了する。つまり、次のようなコードを書くことはできるが、最後の行は実行されない。
def get_ans4ultimateQ():
return 42 # 関数の実行はここで終了
print('can not reach this line') # この行は実行されることはない
return文によって、関数の実行が終了すると、プログラムの実行は「関数呼び出しの次」へと移動する。なお、値を返さない関数を定義しているのであれば、単に「return」とだけ書く。その場合は関数の実行がそこで終了して、その関数を呼び出した側で次のコードが実行される。上で見たhello関数ではreturn文がないが、これは関数本体に記述したコードの最後まで実行されたので、そこで関数の実行が終了して、呼び出し側にNoneが返されたということだ。
この関数を呼び出して、その戻り値を使用するコードは次のように書ける。
result = get_ans4ultimateQ()
print(result)
この場合、関数get_ans4ultimateQが呼び出されて、その実行が終わると、「42」という値が得られる。関数呼び出しの次には、「result = ……」という代入文が実行されるが、この右辺の値となるのが関数呼び出しで得られた値だ。結果、戻り値の「42」が変数resultに代入される。
そして、最後に次の行の「print(result)」が実行される。
実際の実行結果を以下に示す(以下の画像では、return文の後にprint関数呼び出しがあるバージョンを呼び出しているが、print関数による画面表示がないことにも注目しよう)。
一方、次のように書いてもよい。
print(get_ans4ultimateQ())
これは「関数get_ans4ultimateQの呼び出しをprint関数の引数」としている。この場合、関数get_ans4ultimateQを呼び出して得られた戻り値が、そのままprint関数に引き渡される。ただし、変数に値を代入していないので、この関数呼び出しの結果は「使い捨て」となって、後から利用することはできない。このような関数の使い方もあることは覚えておこう。
このコードを入力して関数を呼び出した結果を以下に示す。
関数の名前
上記の関数の名前は「get_ans4ultimateQ」となっている。このうち、「ans」は「answer」を、「4」は「for」を、「Q」は「Question」を意識して付けたものだ。つまり、この名前は「get_answer_for_ultimate_question」(究極の疑問の答えを求める)を短く表記したものだ*2。アンダースコア(_)は複数の単語を連ねたものを関数名とするときに、関数名を読みやすくするために入れたものだ(アンダースコアを入れずに、全ての単語を繋げていくと「getanswerforultimatequestion」となり一目では何を表しているかが分からなくなってしまう)。
関数名は、その関数が何をするものかを分かりやすく説明するものでなくてはならないので、このように長い名前になることがある。ただし、単に単語を連ねただけでは、読みづらい表記になってしまうので、必要に応じて、このようにアンダースコアを含めたり、短縮表記を用いたりすることがよくある。
*2 戻り値の「42」というのはDouglas Adams氏によるSF小説「銀河ヒッチハイク・ガイド」で「究極の疑問」に対する解答としてコンピュータが算出した値だ。Google検索でも「生命、宇宙、そして万物についての究極の疑問の答え」「生命、宇宙、全ての答え」などとして検索すると、この値が得られる。
なお、Pythonにおける「関数の命名規則」は「PEP 8 -- Style Guide for Python Code」と呼ばれるドキュメントで定められている。
関数名には英文字/アンダースコア/数字などを使えるが、「PEP 8」で推奨されているのは「英小文字のみで構成し、読みやすさを考慮して、適宜アンダースコアで単語をつなぐ」命名法だ(そういう意味ではこの関数の名前は微妙だが、「for」を意味する「4」や、「question」を省略した「Q」を使った方が分かりやすいと筆者は感じるが、以降はなるべくPEP 8に従った名前にしていく)。
次にもう少し複雑な処理をして、その結果を返す関数を定義してみよう。
FizzBuzz問題の答えを返す関数
本連載の第9回の「if〜elif〜else文」ではif文の説明の例として「FizzBuzz問題」を解くコードを取り上げた。そのコードは次のようなものだった*3。
*3 第2回「Hello Python」の「もう少し難しいHello Worldプログラム」で触れているように、「Try Jupyter」ページの「Jupyter Notebook」リンクから起動するPython環境では以下のコードがうまく動作しない。対処策としては上記ページにあるように、Binderを使う方法がある。以下では、Binderを使って起動した環境で話を続けることにしよう。
number = input('何か数値を入力してください: ')
number = int(number)
if number % 3 == 0 and number % 5 == 0:
print('FizzBuzz')
elif number % 3 == 0:
print('Fizz')
elif number % 5 == 0:
print('Buzz')
else:
print(number)
このコードは次のような条件を判定するものだ。
- 与えられた数値が3の倍数なら「Fizz」を結果とする
- 与えられた数値が5の倍数なら「Buzz」を結果とする
- 与えられた数値が3の倍数かつ5の倍数なら「FizzBuzz」を結果とする
- それ以外のときには、与えられた数値を結果とする
今度は、この判定を行う部分を「fizzbuzz」という名前の関数として定義してみよう。関数の仕様は次のようになる。
- 関数名:fizzbuzz
- パラメーター:FizzBuzz判定をしたい数値を1つ。パラメーター名は「number」とする
- 戻り値:パラメーターnumberの値が3の倍数なら文字列'Fizz'を、5の倍数なら文字列'Buzz'を、3の倍数かつ5の倍数であれば'FizzBuzz'を、それ以外の場合には与えられた数値を文字列化したものを戻り値とする
関数ボディーで実際に行う処理は既に見た通りなので、基本的にはこれを組み込めばよい。そうすると、fizzbuzz関数は次のようになる(パラメーターnumberをstr関数で文字列化するところだけ変更している*4)。
def fizzbuzz(number):
if number % 3 == 0 and number % 5 == 0:
print('FizzBuzz')
elif number % 3 == 0:
print('Fizz')
elif number % 5 == 0:
print('Buzz')
else:
print(str(number))
*4 パラメーターnumberの値を文字列化しているのは、その値が「3の倍数」「5の倍数」「3の倍数かつ5の倍数」のときには文字列を戻しているので、それらと合わせているからだ。時と場合によって、関数から文字列が返されたり、数値が返されたりすると、それを使用する側にしてみると使いづらい。そこで、ここでは関数が常に文字列を返すように調整しているということだ。
ただし、この関数はまだ値を返さずに、print関数で結果を表示するだけとなっている(正しく判定してその結果を画面に表示はしてくれるので、興味のある方は実行してみよう)。print関数を呼び出すのではなく、それぞれの値を返す必要がある。簡単なのは「print関数呼び出しをreturn文に置き換える」ことだ。すると、関数fizzbuzzは次のようになる。
def fizzbuzz(number):
if number % 3 == 0 and number % 5 == 0:
return 'FizzBuzz'
elif number % 3 == 0:
return 'Fizz'
elif number % 5 == 0:
return 'Buzz'
else:
return str(number)
この場合、if文の各節でreturn文を実行するので、その時点で関数の実行が終了することになる。一方、判定した結果を変数に保存しておいて、関数の最後でそれを返す方法もある。
def fizzbuzz(number):
result = str(number)
if number % 3 == 0 and number % 5 == 0:
result = 'FizzBuzz'
elif number % 3 == 0:
result = 'Fizz'
elif number % 5 == 0:
result = 'Buzz'
return result
こちらのコードでは、最初にパラメーターnumberに受け取った値を変数resultに保存しておき、「3の倍数なら変数resultに'Fizz'を代入」「5の倍数なら'Buzz'を代入」「3の倍数かつ5の倍数なら'FizzBuzz'を代入」し、最後に変数resultの値を返すようにしている。
前者のバージョンでは、if文の各節でそのまま関数の実行が終了するが、後者のバージョンではif文の各節が終了した後に関数末尾で実行されるreturn文で関数が終了する。後者の場合は、if文で得られた結果をさらに加工したり、別の処理を加えたりすることも可能だ。どちらの書き方が適切かは時と場合によるので、いろいろな書き方ができることを意識しよう。
実際にこれを呼び出すコードと組み合わせると次のようになる(ここでは最後のバージョンを使っているが、その前のものでも構わない)。
def fizzbuzz(number):
result = str(number)
if number % 3 == 0 and number % 5 == 0:
result = 'FizzBuzz'
elif number % 3 == 0:
result = 'Fizz'
elif number % 5 == 0:
result = 'Buzz'
return result
number = input('何か数値を入力してください: ')
number = int(number)
print(fizzbuzz(number))
これを実行した結果を以下に示す。
なお、ここでは関数定義(def文)が他のコードよりも先に書かれていることに注意しよう。「def文で関数を定義した後でなければ、その関数を利用することはできない」のだ。つまり、「関数は使う前に定義する」必要がある。
例えば、次のコードを考えてみよう。
print(some_func())
def some_func():
print('you called some_func')
some_func関数の定義とその呼び出しが前後している。これを実行してみるとどうなるだろう。
御覧の通り、エラーが発生した。エラーメッセージをよく見ると「some_funcという名前が定義されていない」とある。関数を定義することで、その名前が定義されるので、関数は使う前に定義することを忘れないようにしよう。
まとめ
関数呼び出しの方法や、関数定義など、今回はPythonの関数の基本について見てきた。関数定義とは「自分が使えるさまざまなプログラム要素を組み合わせて、新たなプログラム要素を組み立てる」という作業である。ここでいう「プログラム要素」には、これまでに見てきた数値や文字列、変数や演算子、関数などのことだ。そして、作成した新たなプログラム要素である関数は、さらに別の関数を定義する際にも利用できる。このように、Pythonが標準で提供しているものを利用して、「できることを増やしていく」ことがプログラミングという作業だといえる。
次回以降では関数内部で使用する変数の有効範囲や関数呼び出し時の引数の渡し方、ラムダ式など、今回取り上げなかった関数についての少し高度な話題を取り上げる。
今回のまとめ:関数
- 関数とは、「何かの値を与えると、それを基に何らかの処理を行い、その結果を返す」もの
- 関数に渡す値を「引数」「実引数」などと呼ぶ
- 関数から戻される値を「戻り値」などと呼ぶ
- 関数に引数を与えて、戻り値を得ることを「関数呼び出し」などと呼ぶ
- 関数を呼び出すには「関数名(引数1, 引数2, ……)」のようにする
- 戻り値を保存するには、変数に代入する
- 関数は「def文」で定義する
- def文では、「関数の名前」「関数の実行に必要なパラメーター」「関数が実行するコード」を記述する
- 関数を呼び出した側に値を戻すには、return文を使う
「Python入門」
Copyright© Digital Advantage Corp. All Rights Reserved.