今回は関数の出力に着目します。
「return文が記述された関数は結果として値を返す」というのは既にご存知の方がほとんどだと思いますが、ではそもそも戻り値/返り値があるとどんないいことがあるのでしょうか?
returnが無い方が便利?
それではまず戻り値が無い関数と、ある関数を比較してみましょう。
最初に戻り値が無い関数。print関数を処理内容に仕込むことによって、関数を呼び出すだけでコンソールに答えが表示されます。
def rad(a):
answer = a*2
print(answer)
rad(3) #6
続いて戻り値がある関数。この場合、関数呼び出しだけではコンソール出力されません。
def rad(a):
answer = a*2
return answer
print(rad(3)) #6
関数の結果をコンソール上で確認するためには、関数呼び出しをprint関数に入れてやらなければなりません。そのため、初学者の方にはこう思われる方も多いかと思います。
「上の方が面倒臭くなくていいじゃん」
確かにこの超どシンプルなコードの場合、戻り値が無い関数の方が若干記述が少なく済むかもしれません。
returnが無い関数の問題点
ではもう少しだけ複雑にしてみましょう。
rad関数に渡す引数aの値が3,8,19のとき、円の面積はそれぞれいくつでしょうか?
円の面積を計算する関数を新たに定義して答えましょう。
この問題、戻り値がある関数を使えば非常に簡単に計算ができます。
#半径を求める関数
def rad(a):
answer = a*2
return answer
#円の面積を計算する関数
def area(b):
answer = b*b*3.14
return answer
#rad関数の戻り値を変数に代入
x = rad(3)
y = rad(8)
z = rad(19)
print(area(x)) #113.04
print(area(y)) #803.84
print(area(z)) #4534.16
下側の3つの変数に注目してみましょう。x,y,zという変数にはそれぞれ、rad関数の呼び出しがそのまま代入されています。
至ってシンプルな代入です。しかしこの行為、returnが無い関数では不可能です。
def rad(a):
answer = a*2
print(answer)
x = rad(3) #6
print(x) #None
このコードの実行結果は非常におかしなものになってしまいます。実行結果は「6」と「None」です。
本来の趣旨とは少し離れますが、まずはなぜ「6」が表示されてしまうのかについてお話しておきましょう。
なぜ「6」が出るのか?
まず大前提として、関数は()を付けて呼び出すと、その時点で実行されます。
rad関数にはprint()が内部処理として存在しています。そのため「x = rad(3)」の時点で関数は1度実行され、print(answer)の結果が表示されてしまいます。
この問題はreturnの有無に関わらず起こります。関数を実行せずに別名として変数に入れるのであれば「x = rad」と()を付けずに代入しましょう。
その場合、rad関数の呼び出しは変数xに()を付けて、「x(3)」でも可能になります。
なぜ結果が「None」になるのか?
今回の趣旨はこちら。returnが記述されていない関数呼び出しの結果は、どうあがいても「None」になります。
Noneとは「何も無い」ということです。この関数には出力が無いため、関数呼び出しの戻り値はありません。
ということは、この関数の実行結果は、関数の外側に持ち出すことができないということになります。これが戻り値が無い関数の一番の問題です。
図で比較してみる
この2つの関数の処理の流れを図で比較してみることにしましょう。
returnがある関数を呼び出したときの流れはこんな感じになります。
引数という入力があり、returnという出力があります。
returnがあることによって、rad関数の結果は関数の外に出ることができます。それによってこの「6」は、コードの他の場所に持ち出せるわけです。
しかしreturnが無い関数は…
関数の出口が閉ざされてしまっているため、実行結果は処理が終了した時点で失われてしまいます。結果は「None」です。
「その関数の実行結果を他のどこにも持ち出さない」という前提が無ければ、戻り値が無い関数を作るべきではないと言えます(メソッドとなると話は別になりますが、別の機会にお話したいと思います)。