プログラミング

Python超入門⑤ 関数で処理をまとめよう

def、引数、戻り値、デフォルト引数、変数のスコープを学び、処理を読みやすく分けます。

似た処理を何度もコピーしていると、「1か所直したのに、もう1か所は直し忘れた!」ということが起きます。

そんなときに役立つのが関数です。処理に名前を付けてまとめ、必要なところから呼び出せるようにします。今回は、あいさつを表示する小さな関数から始めて、計算結果を返す関数へ進みましょう。

今回分かるようにしたいこと

  • def で関数を作り、呼び出す
  • 引数で値を渡す
  • return で結果を返す
  • 表示することと、結果を返すことを区別する

この記事はPython 3用です。各コード欄は、別々の例として実行してください。変数とif文を使います。関数の説明の中にも新しい言葉が出るので、1つずつ確認していきます。

1. 関数を「作る」と「使う」は別の操作

まずは3行の例

def greet():
    print("こんにちは")

greet()
こんにちは

def は「関数を定義する」、つまり処理に名前を付けて用意するためのキーワードです。greet が付けた名前で、greet() と書くと使えます。この「使う」操作を呼び出しといいます。

部分 役割
def 関数を用意する
greet 関数の名前
() 今回は渡す値がないため空
: 関数の処理がここから続くことを示す
字下げした行 呼び出されたときに動く処理
最後の greet() 用意した関数を呼び出す

定義しただけでは、あいさつは出ない

最後の greet() を消すと、何も表示されません。関数を用意することと、中の処理を実行することは別だからです。

実行の順番は、こうなります。

  1. def の行で、greetという関数を用意する
  2. 字下げされた中身は、まだ実行しない
  3. 下の greet() で関数を呼ぶ
  4. 関数の中へ進み、「こんにちは」を表示する
  5. 関数を呼んだ場所へ戻る

ここがつかめると、コードを上から読んだときに「なぜ途中の行を飛ばすの?」という疑問も減ってきます。関数定義の公式説明でも、この定義と実行の違いを確認できます。

2. 引数で「今回使う値」を渡す

名前だけ変えて、同じ処理を使う

def greet(name):
    print(f"こんにちは、{name}さん")

greet("Aoi")
greet("Ren")
こんにちは、Aoiさん
こんにちは、Renさん

greet("Aoi") の "Aoi" は、関数へ渡す引数(ひきすう)です。関数側の name が、その値を受け取るための名前になります。

厳密には、定義側の name を仮引数、呼び出し側の "Aoi" を実引数と区別します。ただ、最初は「受け取る名前」と「渡す値」を見分けられれば十分です。

1回目と2回目を分けて考える

呼び出し その回のname 表示
greet("Aoi") "Aoi" こんにちは、Aoiさん
greet("Ren") "Ren" こんにちは、Renさん

あいさつの文章を変えたければ、関数の中を1か所直せば済みます。「同じ処理を何度も書かなくていい」という便利さは、ここにあります。

ただし、greet(name) と定義しているのに greet() と値を渡さず呼ぶと、必要な引数がないため TypeError になります。引数の数が合っているかも確認しましょう。

3. returnは、結果を呼び出し元へ返す

計算した結果を、後でも使いたい

次は、商品の小計を計算する関数です。

def subtotal(price, count):
    return price * count

amount = subtotal(160, 3)
print(amount)
print(amount + 100)
480
580

戻り値(もどりち)は、関数から返される結果です。return の後ろに書いた値が、関数を呼んだ場所へ戻ります。

動きを分けてみましょう。

  1. subtotal(160, 3) を呼び出す
  2. 関数の中では price が160、count が3になる
  3. price * count を計算し、480を得る
  4. return が480を返す
  5. amount = subtotal(160, 3) の呼び出し結果が480になり、amount に代入される

次の行では、その結果をさらに計算できます。関数は「画面に出すだけのもの」ではないんですね。

printとreturnを混ぜない

def show_subtotal(price, count):
    print(price * count)

result = show_subtotal(160, 3)
print(result)
480
None

「480を出しているのに、なぜNone?」と感じるかもしれません。

print() は画面へ表示する操作です。それだけでは、関数の戻り値を480にできません。return で値を返さずに関数の最後まで進むと、Noneという「ここでは返す値を用意していない」ことを表す値が返ります。

書き方 画面へ表示 後の計算に結果を渡す
print(price * count) する この行だけではできない
return price * count しない できる

計算する関数は計算結果を返し、呼び出した側で表示する。この分け方にすると、画面表示以外にも結果を使いやすくなります。returnの正式な動作も参考になります。

4. returnに到達したら、その関数は終わる

def shipping_fee(total):
    if total >= 3000:
        return 0
    return 300

print(shipping_fee(3200))
print(shipping_fee(1800))
0
300

これは「3000円以上なら送料0円、それ以外は300円」という練習用に決めたルールです。特定のお店の料金ではありません。

3200の場合、最初の return 0 で関数が終わるため、後ろの return 300 は実行されません。1800ならif文の中に入らず、最後の行で300が返ります。

return は「ここまでの結果を返して、この関数を終える」と読むと分かりやすいです。プログラム全体を終了するわけではなく、呼び出し元へ戻ります。

5. 省略したときの値を決める:デフォルト引数

def greet(name, message="こんにちは"):
    return f"{message}、{name}さん"

print(greet("Aoi"))
print(greet("Ren", "おはよう"))
print(greet("Mio"))
こんにちは、Aoiさん
おはよう、Renさん
こんにちは、Mioさん

message="こんにちは" は、messageを省略したときに使うデフォルト値です。

2回目では "おはよう" を渡していますが、これはその呼び出しで使う値を指定しただけ。デフォルト値そのものを書き換えたわけではないので、3回目は「こんにちは」に戻ります。

公式には、デフォルト値は関数を定義するときに評価されます。そのため、変更できるリストなどをデフォルト値にすると、意図せず呼び出し間で共有されることがあります。まずは、この例のような文字列や数値で使い方を覚えましょう。デフォルト引数の注意点

6. スコープ:その名前をどこから使える?

スコープは、変数などの名前が使える範囲のことです。関数の中で代入した名前は、基本的にその関数の中で使うローカル変数になります。

def make_message():
    message = "準備できました"
    return message

text = make_message()
print(text)
準備できました

関数の外から message を直接使おうとすると、この例では NameError になります。でも、値を return で返して、外側の text で受け取ることはできます。

名前の使える範囲と、値を渡せるかどうかは別の話です。「中の変数を無理に外へ見せる」のではなく、必要なものを引数で渡し、結果を戻り値で受け取ると、処理のつながりが読みやすくなります。

7. 練習:大きい方を返す関数を作ろう

2つの数を受け取り、大きい方を返す larger 関数を作ってください。数が同じ場合は、その数を返します。

確認用の例は3つです。

  • larger(12, 7) → 12
  • larger(4, 9) → 9
  • larger(5, 5) → 5

模範解答

def larger(a, b):
    if a >= b:
        return a
    return b

print(larger(12, 7))
print(larger(4, 9))
print(larger(5, 5))
12
9
5

解説:どのreturnを通る?

a >= b は「aがb以上か」という条件です。

aとb 条件 返す値
12と7 True 最初のreturnで12
4と9 False 最後のreturnで9
5と5 True 最初のreturnで5

最初の return が実行されたら関数は終わるので、この例では else がなくても動きます。もちろん、else を使って書いても構いません。

同じ値の場合まで試すのは、境界の確認のためです。「普段の入力では動くけれど、同じ数のときだけ違う」といったミスを見つけやすくなります。

まとめ:値の行き来が見えれば大丈夫

関数の最初の山場は、def の書き方よりも「いつ実行され、どこへ戻るか」です。

呼び出し → 引数を受け取る → 処理する → returnで返す → 呼び出した場所へ戻る。

この順番を追えれば、長いプログラムも小さな仕事に分けて読めるようになります。最初から何でも関数にする必要はありません。同じ処理が繰り返されたときや、ひとまとまりに名前を付けたくなったときに使ってみましょう。

前の記事:Python超入門④ 繰り返し

次の記事:Python超入門⑥ リストと辞書

← 記事一覧へ戻る