Python 関数の引数と戻り値【サービスとして捉える視点解説】

Python
この記事は約18分で読めます。

こんにちは、ナナです。

前回の記事『Python 関数定義と呼び出し方とは【関数の扱い方を知ろう】』では、関数定義と関数呼び出しの基本を学びました。

この記事では『関数』を、もう少し本格的なレベルに深堀りしていきます。

関数には「処理をまとめる」以外に「サービスを提供する」という見方があり、そこには『引数』と『戻り値』という新しい要素を理解する必要があります。

本記事では次の疑問点を解消する内容となっています。

本記事で学習できること
  • 『関数』をサービスとして捉えるイメージとは?
  • 関数の『引数』の役割と使い方とは?
  • 引数を持つ関数のプログラム方法とは?
  • 関数の『戻り値』の役割と使い方とは?
  • 戻り値を持つ関数のプログラム方法とは?
  • return命令の使い方とは?
  • C言語技術者が知るべきPythonとの違いとは?

では、『関数』とは『サービスを提供するもの』という極意を学んでいきましょう。

  1. 『関数』とは『サービスを提供するもの』である
    1. 振り返ります!『関数』の役割の基本は「処理をまとめること」
    2. 『サービス』とは、いったいなんでしょう?
    3. 関数は『サービスを提供する』モノとしてイメージする
  2. 『引数』:関数呼び出し側から関数定義側に依頼するメッセージ
    1. 『引数』の役割とは?
    2. 関数の引数の種類は、関数定義側が決定する
    3. 引数を持つ関数の定義書式
    4. 引数を持つ関数定義のプログラム例
    5. 「print命令」は実は「print関数」だった
  3. 戻り値:関数定義側から関数呼び出し側へ伝えるメッセージ
    1. 『戻り値』の役割とは?
    2. 『戻り値』の情報を渡すための「return命令」
    3. 「return命令」は関数の処理を途中で終了するためのものでもある
  4. Q&A:関数の『引数』と『戻り値』に関するよくある質問
    1. Q:関数の引数として間違った情報を渡したらどうなるの?
    2. Q:戻り値のない関数から、『戻り値』を取得しようとするとどうなるの?
  5. 課題:関数の『引数』と『戻り値』が学べたかを確認しよう
    1. 課題1:関数の『引数』を使ってみよう
    2. 課題2:関数の『戻り値』を使ってみよう
    3. 課題3:関数で複雑な処理を作ってみよう その1
    4. 課題4:関数で複雑な処理を作ってみよう その2
  6. C言語技術者が知るべきPython言語との違い:「関数」の引数と戻り値
スポンサーリンク

『関数』とは『サービスを提供するもの』である

『関数とはサービスである』

この言葉はC言語を学んだ時に言われていたことと同じですね。復習も兼ねてもう一度聞きたいのです。

ナナ
ナナ

そうだね。プログラミングを始めたばかりの人は、この『関数』という機能が何なのかを理解できないことって結構あるんです。

だから、何度も繰り返し読み返すことで理解するとよいですよ。

『関数』はプログラムを構成する主要な要素です。そのため、必ず身に付ける必要があります。

振り返ります!『関数』の役割の基本は「処理をまとめること」

前回、『関数』とは複数の処理をまとめたものである、と解説しました。

# 関数定義
def hello():
    print("こんにちは")
    print("ナナです")

このように、hello関数の定義としてprint命令であいさつを行うようにしておきます。

あいさつをしたい時は、次のようにhello関数を呼び出せばいつでもこのプログラムを動かすことができるのでした。

# 関数呼び出し
hello()

これだけでも便利は便利なのですが、『関数』はもっと様々なことができる優秀な機能なんです。

『サービス』とは、いったいなんでしょう?

関数の理解ができない方の特徴として、関数を『サービス』としてイメージ化していないことが挙げられます。

まず、『関数とはサービスである』という言葉を理解するには『サービス』とは何か、を考える必要があります。

普段は意識していないかもしれませんが、皆さんは日常において様々なサービスを受けたり、逆にサービスを提供する側でもあったりします。

サービスとは何か

このように『サービス』とは依頼する側の要求に対して、要求を満たしてくれるものです。

つまり『サービス』とは、次の2者によって成立します。

サービスの概要

このイメージをプログラムの『関数』に当てはめることで、『関数』を理解していきます。

関数は『サービスを提供する』モノとしてイメージする

『サービス』を『関数』と同じモノとして捉えると、つぎのようになります。

関数をサービスとして捉える

『関数』においての2者とは「関数を呼ぶ側」と「関数を定義する側」になります。これが『サービス』の要求側と提供側にそのまま置き換わります。

ナナ
ナナ

『関数』を『サービス』としてイメージすること!これが『関数』を理解する上での近道なんです!理解できるまで読み返してください。

スポンサーリンク

『引数』:関数呼び出し側から関数定義側に依頼するメッセージ

『サービス』として店員さんに注文を依頼するときって、言葉で「コーヒーを1つください」とかって伝えるじゃないですか。

これってどうやってプログラムの『関数』では伝えるんですか?

ナナ
ナナ

その通りだね。『サービス』の「依頼者」と「提供者」を結ぶための会話に相当するものが、プログラムでもやはり必要になります。

まずは、依頼する側が提供側に情報を伝える方法を説明します。これを関数の『引数』と呼びます。

『引数』の役割とは?

引数ひきすうとはプログラムにおいて、「関数を呼び出す側」が「関数を定義する側」に伝えるメッセージを入れるための変数のことです。

関数の引数は変数で渡す

『サービス』を要求する側というのは『引数』とよばれる変数の箱に伝えるべきメッセージを入れて関数定義側へ渡すのです。

関数の引数の種類は、関数定義側が決定する

『関数』によって『引数』として必要な情報は異なります。

それは次のように『サービス』によってサービスを動かすために必要となる「情報の種類」が異なることと同じです。

サービスに必要な情報の種類はサービス提供側が決める

例えば、「コンビニのレジ打ち」サービスに、「起床したい時刻」を伝えても意味がありません。

どのような種類の情報によってサービスが動くかは「サービス提供側」が決定権を握っています。

引数を持つ関数の定義書式

『引数』を必要とする関数定義の書き方は次のものです。

引数が必要な関数定義の書き方

 def 関数名引数の変数名A, 引数の変数名B):
   関数として行う処理①
   関数として行う処理②

『引数』は()の中に変数名を書くことで定義します。変数名は自由に皆さんが決めることができますが、その情報の意味を表す名前にしておくとよいでしょう。

『引数』となる変数の個数は、いくつでも定義することができます。『引数』が必要ない関数の場合は省略することができます。

ナナ
ナナ

関数の引数は()の中に並べるというのは、多くのプログラミング言語で採用している指定方式です。

一度この考え方を学べば、他の言語でもすぐに理解できますよ。

引数を持つ関数定義のプログラム例

ものすごく簡単な関数ですが、『引数』を持つ関数を定義したプログラム例です。

2つの数値を受け取って、画面に足し算した結果を表示する「print_sum関数」を定義します。

# 2つの引数として数値を受け取る関数定義
def print_sum(x1, x2):
    print(x1 + x2)

このprint_sum関数というサービスを利用したい側は、『引数』へ2つの数値を指定してprint_sum関数を呼び出します。

# 関数呼び出し側は引数に具体的な数値を指定
print_sum(10, 20)
引数で情報を渡すとは
ナナ
ナナ

『引数』の情報の種類を決めるのは関数定義側、『引数』の具体的な値を指定するのは関数呼び出し側になります。

この違いをしっかりと理解してください。

「print命令」は実は「print関数」だった

ここまでくると薄々感じている方もいるかもしれません。今までたくさん登場した「print命令」とは実は「print関数」なのです。

print関数をサービスとして捉える
# print関数を呼び出している
print("Hello")

printという関数名に()を付けることで、print関数を呼び出していたということですね。

このprint関数を呼び出す時に()の中に記述した”Hello”こそが、『引数』として渡したメッセージです。

print関数の引数

print関数が提供するサービスとは、要求側が表示したいあらゆる情報を画面に表示することです。画面に表示すべき文字を決めるのは「サービスを要求する側」なのです。

そのため『引数』というものを利用して、関数定義側に情報を渡しているのです。

ナナ
ナナ

『引数』は関数を理解するために必ず必要な知識です。引数を利用することで、様々な要求を関数側に行うことができるようになるのです。

スポンサーリンク

戻り値:関数定義側から関数呼び出し側へ伝えるメッセージ

要求側は『引数』を使って、サービスである『関数』へ情報を渡すんですね。それでは『関数』から要求側へ情報を渡すためにはどうすればいいんですか?

ナナ
ナナ

今度は逆方向の情報提供だね。その場合は『戻り値』を使って情報を渡すことになります。

『戻り値』の役割とは?

戻り値もどりちとはプログラムにおいて「関数を定義する側」が「関数を呼び出した側」に伝えるメッセージを入れるための情報のことです。

関数の結果は戻り値で返す

『関数定義をする側』は、サービスを実行した結果を『戻り値』として指定し、メッセージを『関数呼び出し側』へ情報を返却するのです。

『戻り値』の情報を渡すための「return命令」

関数定義側が『戻り値』で情報を返却するためには、「return命令」という特別な命令を書く必要があります。

関数定義側では次のようにreturn命令を書くことで、関数呼び出し側に情報を渡すことができます。2つの引数の数値を足し算した結果を『戻り値』として返却する関数定義です。

# 2つの引数として数値を受け取る関数定義
def get_sum(x1, x2):
    # 引数情報を足し算し戻り値で返却する
    return x1 + x2

関数呼び出し側では、次のように『戻り値』を受けとります。

# 足し算した結果を戻り値で取得
result = get_sum(10, 20)
print(result)
戻り値の受け取り方

『引数』でサービスの依頼を行い、『戻り値』でサービスの結果を受け取る。これが関数のサービスとしての姿です。

ナナ
ナナ

変数名 = 関数名(引数)として戻り値の情報を受け取ります。この形をしっかりと理解してください。

「return命令」は関数の処理を途中で終了するためのものでもある

「return命令」について補足しておきましょう。

「return命令」は戻り値の情報を呼び出し側へ返却する命令ですが、その他にも関数の処理を途中で終了させる目的でも使用されます。

# 割り算の結果を画面に表示する関数定義
def print_division(num, div):
    # 0割りをするときは処理を終了
    if div == 0:
        return

    print(num / div)
    return


# 割る値として「0」を指定した
print_division(10, 0)

数学の世界では数値を「0」で割るということは許されていません。そのため、もしも「0」が指定された場合は、チェックしてreturn命令で関数の処理を強制終了し、呼び出し元へ戻ります。

このようなシーンで「return命令」を使うこともよくあるのです。

ナナ
ナナ

このように「return命令」は関数の中で複数書くこともできます。

スポンサーリンク

Q&A:関数の『引数』と『戻り値』に関するよくある質問

ナナ
ナナ

関数の『引数』『戻り値』でわからないことある人はいるかなー?

Q:関数の引数として間違った情報を渡したらどうなるの?

師匠!Pythonって変数にどんな情報でも入れることができるじゃないですか!もしも、数値を渡すべき引数に文字列を渡しちゃったらどうなるんですか?

気になります!

ナナ
ナナ

うんうん、いいところに目を向けたね。Pythonという言語はデータ型に対して柔軟性が高い分だけ、逆に危険なこともあるんだよ。

それは『引数』として受け渡すべき情報のルールが守られないときだね。

それでは、具体的な例として数値として渡されるべき『引数』に対して、文字列を渡してしまった場合にどうなるかを見てみましょう。

# 2つの引数として数値を受け取る関数定義
def print_sum(x1, x2):
    print(x1 + x2)


# 関数呼び出しで第1引数に文字列を指定してしまった
print_sum("Hello", 20)

プログラムを実行すると、次のエラーが発生します。

  File "C:/PythonProject/project1/main.py", line 7, in <module>
    print_sum("Hello", 20)
  File "C:/PythonProject/project1/main.py", line 3, in print_sum
    print(x1 + x2)
TypeError: can only concatenate str (not "int") to str

このエラーは、文字列を管理している「x1」変数と、数値を管理している「x2」変数を足し算しようとして「str型とint型は文字として結合できません」というエラー内容です。

このようにPythonでは、実行した結果「ダメじゃん!」ということが発生します。

それでは次に、引数として文字列を2つ与えた場合はどうなるかを試してみましょう。

# 2つの引数として数値を受け取る関数定義
def print_sum(x1, x2):
    print(x1 + x2)


# 第1,2引数に文字列を指定してしまった
print_sum("Hello", "World")

実行結果は、次のものとなります。

HelloWorld

なんと文字列が結合された文字列が正常な結果として表示されてしまいました。数値の足し算の結果を出すべき関数が、文字列を結合する関数になってしまったのです。

このように予期せぬ情報を引数で渡してしまうと、プログラム次第で予想していない結果が発生してしまいます。これは要注意です!

ナナ
ナナ

Pythonの持つデータ型の柔軟性が悪い方向に出てしまうと、こんな結果になってしまいます。

このようにPythonは安全性という点においては、皆さんが気を付けないと予期せぬ問題が発生することを知らなければなりません。

Q:戻り値のない関数から、『戻り値』を取得しようとするとどうなるの?

師匠!それじゃあ、戻り値のない関数から『戻り値』を得ようとしてしまった場合はどうなっちゃうんですか?

謎の値、すなわち「不定値」となってしまうってことじゃないですか!そこ、どうなんですかっ!

ナナ
ナナ

熱い討論になってきたよ。それじゃあ、戻り値のない関数から無理やり関数の戻り値を受け取るプログラムを作って確認してみよう。

なんでも実験が大切だよ。こうやって言語の仕組みを学んでいくんだよ。

それでは次のように戻り値のないtest関数に対して、戻り値を取得するプログラムを動かすとどうなるかを示しましょう。

# 戻り値のない関数定義
def test():
    return


# 戻り値のない関数で戻り値を取得しようとした
result = test()
print(result)
None

実行した結果「None」と表示されました。これは、変数が空っぽですという意味です。

このように不定な値というわけでなく、「ない」という状態として管理されることになります。

ナナ
ナナ

Pythonにおける「None」とは、C言語における「NULLポインタ」に相当するような状態と言えます。正当な情報を持っていない状態ということですね。

スポンサーリンク

課題:関数の『引数』と『戻り値』が学べたかを確認しよう

ナナ
ナナ

もしも、プログラムが上手く動かなくて困ったときは、答えを見るのではなく「デバッガ」の使い方を学びましょう。

この記事を見ると問題の解決技術が身に付きます。困ったときのオススメ記事です!

課題1:関数の『引数』を使ってみよう

課題内容

次の要求を満たす関数を定義せよ。

関数名print_tax_price
処理概要第1引数として渡された税抜き価格から税込み価格を画面表示する
第1引数変数名price。税抜き価格を指定する
備考税額は一律10%とすること

この関数に引数として「1500」を指定して呼び出せ。


出力期待結果

1650.0000000000002


『引数』の定義方法と関数の呼び出し方を理解しましょう。

# 引数で税抜き価格を受け取り税込み価格を表示する関数定義
def print_tax_price(price):
    print(price * 1.10)


# 税抜き1500円の税込み金額を表示要求
print_tax_price(1500)
ナナ
ナナ

『引数』の扱い方は必ず習得しましょう。今後、必ず必要となる技術です。

課題2:関数の『戻り値』を使ってみよう

課題内容

次の要求を満たす関数を定義せよ。

関数名get_triangle_area
処理概要引数で指定された底辺と高さから三角形の面積を求め戻り値とする
第1引数変数名bottom。底辺の長さを指定する
第2引数変数名height。高さの長さを指定する
戻り値算出した三角形の面積を返却する
備考三角形の面積は「底辺 × 高さ ÷ 2」とする

この関数に引数として「底辺:30」「高さ:50」を指定して呼び出し面積を取得せよ。また、取得した面積は、print関数を使って画面に表示せよ。


出力期待結果

750.0


関数を呼び出し側において『戻り値』の取得方法を理解しましょう。

# 三角形の面積を求める関数定義
def get_triangle_area(bottom, height):
    return bottom * height / 2


# 底辺と高さを与え戻り値で面積を取得する
area = get_triangle_area(30, 50)
print(area)
ナナ
ナナ

『引数』と『戻り値』の使い方を確実に抑えていきましょう。

課題3:関数で複雑な処理を作ってみよう その1

課題内容

次の要求を満たす関数を定義せよ。

関数名print_square
処理概要引数で指定された1辺の長さとする四角形の図形を表示する
第1引数変数名length。1辺の長さを指定する
戻り値なし
備考図形の記号は「*」を使用する

この関数に引数として「辺の長さ:5」を指定して呼び出し図形を表示せよ。


出力期待結果

辺の長さが「5」の場合

*****
*****
*****
*****
*****

辺の長さが「7」の場合

*******
*******
*******
*******
*******
*******
*******


関数の中でfor文を利用するプログラムです。

このようにプログラムを関数化することで、関数を呼び出せばいつでも図形記号を表示できるようになります。

# 四角形の図形を表示する関数定義
def print_square(length):
    for i in range(0, length):
        for j in range(0, length):
            print("*", end="")  # 改行なしで「*」を表示
        print()                 # 改行


# 引数で辺の長さを指定する
print_square(5)
print_square(7)
*****
*****
*****
*****
*****
*******
*******
*******
*******
*******
*******
*******
ナナ
ナナ

これが『関数』のサービスとしての利用シーンです。

これでいつでも関数さえ呼べば、任意の長さの図形を表示することが可能になりました。

課題4:関数で複雑な処理を作ってみよう その2

課題内容

次の要求を満たす関数を定義せよ。

関数名print_triangle
処理概要引数で指定された1辺の長さとする直角三角形の図形を表示する
第1引数変数名length。1辺の長さを指定する
戻り値なし
備考図形の記号は半角空白と「*」を使用する。
右側に寄せた直角三角形とする。

この関数に引数として「辺の長さ:5」を指定して呼び出し図形を表示せよ。


出力期待結果

辺の長さが「5」の場合

    *
   **
  ***
 ****
*****

辺の長さが「7」の場合

      *
     **
    ***
   ****
  *****
 ******
*******


少し難しい問題です。これくらいの問題になると解き方はいろいろ出てきます。解答例を示しましょう。

for文をのみを使ったプログラム例

# 四角形の図形を表示する関数定義
def print_triangle(length):
    for i in range(0, length):

        # 空白を必要な数だけ表示
        for j in range(0, length - i - 1):
            print(" ", end="")

        # 「*」を必要な数だけ表示
        for j in range(0, i + 1):
            print("*", end="")

        print()     # 改行を行う


# 引数で辺の長さを指定する
print_triangle(5)
print_triangle(7)

for文とif文を組み合わせたプログラム例

# 四角形の図形を表示する関数定義
def print_triangle(length):
    for i in range(0, length):
        for j in range(0, length):
            if j < length - i - 1:
                print(" ", end="")
            else:
                print("*", end="")

        print()     # 改行を行う


# 引数で辺の長さを指定する
print_triangle(5)
print_triangle(7)

いずれも、次のように直角三角形を表示できます。

    *
   **
  ***
 ****
*****
      *
     **
    ***
   ****
  *****
 ******
*******
ナナ
ナナ

少しずつ問題を難しくしていきますよ。

スポンサーリンク

C言語技術者が知るべきPython言語との違い:「関数」の引数と戻り値

ナナ
ナナ

すでにC言語を習得している人は、次のポイントに気を付けよう!

C言語技術者が知るべきPythonの特徴
  • Pythonの関数にはデータ型の指定が一切ない
  • 引数と戻り値の考え方は一緒
  • 実は戻り値を複数返すことも可能
  • データ型がないため、情報の受け渡しに注意が必要
  • return命令で戻り値を返さないときに戻り値を取得すると「None」となる

もっとも特徴的なのが、引数や戻り値のデータ型の指定が存在しないことです。

型に柔軟なPythonならではですが、C言語技術者の目線ではデータ型の正当性に対して保証がないことに不安を感じるかもしれませんね。

また、本記事では解説していませんが、Pythonでは戻り値を一度に複数返却することが可能です。別途解説しましょう。