
武蔵野個別指導塾の特徴
高校情報I 関数と引数と戻り値—処理の入口と出口を決めて再利用できる形にする|武蔵野個別指導塾

所要時間を分から時間と分へ変換し、表示と呼出し元への受け渡しを区別し、再利用に役立つのが戻り値です。
よくあるのは、関数の中で表示した値が、呼出し元にも自動で戻ると思い込む場面です。画面に数が見えても、その数を次の計算に使えるとは限りません。所要時間を分から時間と分へ直す処理を作り、値の受け渡しを追います。
入口と出口を問う3つの形
第1の形は、呼出し時にどの値がどの名前に渡るかを追う問題です。関数を定義するときの名前と、呼び出すときに渡す値を対応させます。第2の形は、呼出し後の変数や画面表示を答える問題です。画面に出る文字と、呼出し式が受け取る値を別の欄に記録します。第3の形は、呼出し側で結果を使えるように関数を設計する問題です。入力の範囲、返す値の型、異常な入力の扱いまで決めます。
以下の変換では、入力は0以上の整数の分数です。出力は時間と残りの分をこの順に並べた2要素のタプルとし、残りの分は0以上60未満とします。例えば入力が125なら、2時間5分なので (2, 5) です。負の数や文字はこの仕様の入力ではありません。後の例では、前提外の入力に対して明示的に例外を出す設計も試します。
名前を通る値と、画面へ出る文字
def は関数の名前、仮引数、処理を定義します。定義した時点では関数本体は実行されません。呼び出すと、渡した実引数が仮引数に対応し、本体が実行されます。return は呼出し元に値を返し、そこで関数の実行を終えます。print は画面に表示する処理で、その表示自体は呼出し元に値を返す指示ではありません。
図1のように、呼出し側から実引数が入口へ入り、関数内の仮引数で受け取られます。出口から返った値は、呼出し式を置いた場所で使えます。表示は画面へ向かう別の経路です。

図1では、戻り値と表示の行き先が違います。関数の中で作った hours や minutes は局所変数です。呼出し中の関数内で使う名前であり、同じ名前の変数が呼出し側にあっても別に扱います。値を呼出し側へ渡すには return を使います。名前が同じかどうかではなく、どこで作られた名前かを確認します。
return に複数の値をコンマで並べると、ここでは2要素のタプルとして返ります。呼出し側では1つの変数にタプルを保存することも、2つの変数に分けて受け取ることもできます。処理を複数箇所から呼ぶとき、入口と出口の約束が固定されていれば、呼出し側は変換の詳細を書き直さずに結果を利用できます。
基本例題:所要時間を分ける
図書の整理にかかった125分を、時間と残りの分の組に直します。入力は0以上の整数、答えは時間と分のタプルです。125は60が2つと5の組ですから、期待値は (2, 5) です。2時間を分に戻して5分を加えると125分となり、残りの5も60未満です。
def split_time(total):
hours = total // 60
minutes = total % 60
return hours, minutes
result = split_time(125)
print(result)
1行目で関数を定義し、仮引数を total と名付けます。2行目は60で割った整数の商を hours に保存し、3行目は余りを minutes に保存します。4行目で両方を返します。空行の後、呼出し側で実引数125を渡し、返ったタプルを result に代入します。最後の行でその変数を表示します。関数の定義中には表示がなく、同じ結果を表示以外にも使えます。
図2のように、呼出しで total が125となり、商2と余り5を作ります。返された組は呼出し側の result に入ります。値125と名前 total は同じものではなく、名前がその値を参照するという関係です。

図2の各段階を表にすると、次のようになります。定義時にはまだ total の値は決まっていません。
段階 total hours minutes result
呼出し直後 125 未設定 未設定 未設定
商を保存 125 2 未設定 未設定
余りを保存 125 2 5 未設定
呼出し側に戻る 範囲外 範囲外 範囲外 (2, 5)
Python 3.14.8で実行し、入力125、期待される表示 (2, 5)、実際の表示 (2, 5) を照合しました。局所変数が範囲外という表記は、呼出し側からその名前を直接使えない意味です。計算結果そのものはタプルとして呼出し側に届いています。
同じ入口を使って異なる場面へ返す
標準例題では、準備に80分、片付けに47分かかったとします。それぞれを変換し、さらに合計127分も変換します。3回の呼出しは互いに独立し、前の呼出しの duration を次へ持ち越しません。答えは各タプルとし、合計は元の分数を足してから変換するものとします。
def split_time(duration):
hours = duration // 60
minutes = duration % 60
return hours, minutes
a = split_time(80)
b = split_time(47)
c = split_time(80 + 47)
print(a, b, c)
実引数80では hours が1、minutes が20です。47では0と47、127では2と7です。期待される表示は (1, 20) (0, 47) (2, 7) で、Python 3.14.8の実際の表示も同じでした。元の分数に戻すと、それぞれ80、47、127です。個別の時間と分の組を文字列としてつなげるのではなく、元の分を加算してから変換することで、60分を超える部分も時間へ繰り上がります。
この処理に反復はありません。各呼出しでは商、余り、返却の順に有限個の文が実行され、return で本体を抜けます。実行例は設計の誤りを探す材料ですが、少数の結果の一致だけで全入力に対する正しさを証明したことにはなりません。非負整数を正の60で割った商と余りは、元の数を「商の60倍と余りの和」に戻し、余りを0以上60未満にするため、この変換の約束を満たします。
前提外をどう返すか
少し難しい例題では、入力の検査も入口の約束に含めます。0以上の整数を受け取り、負の整数には ValueError、整数でない値には TypeError を出す仕様です。真偽値はPythonでは整数として扱える場合がありますが、時間の分数として受け取らないため、ここでは型がちょうど整数であることを調べます。例外は通常の戻り値とは別で、呼出し側が捕まえなければそこで処理が中断されます。
def checked_time(total):
if type(total) is not int:
raise TypeError("integer required")
if total < 0:
raise ValueError("nonnegative required")
hours = total // 60
minutes = total % 60
return hours, minutes
for value in (0, 60, 61, -1, "61", True):
try:
print(value, checked_time(value))
except (TypeError, ValueError) as error:
print(value, type(error).__name__)
先に型を検査するので、文字を0と比較して予期しない箇所で失敗する前に、入口で拒否できます。次に負の数を拒否し、有効な値は先ほどと同じ商と余りに進みます。反復は6個の値を順に取り出した後に終わります。try 内の呼出しが例外を出した場合、同じ行の print は完了せず、except が例外の型名を表示して次の値へ進みます。
Python 3.14.8での期待表示と実際の表示は次のとおりです。成功3件に加え、負数、文字、真偽値の失敗3件を別々に確かめています。
0 (0, 0)
60 (1, 0)
61 (1, 1)
-1 ValueError
61 TypeError
True TypeError
表示された2行の 61 は見た目が同じでも、前者は整数、後者は文字列です。0分は0時間0分、60分は1時間0分、61分は1時間1分に戻ることを手でも照合できます。検査を付けない基本関数では、前提外の入力に同じ例外を保証しません。仕様を変えたら、呼出し側も例外に対応する必要があります。
外部の時計や通信先を呼ぶ処理はこの関数に含めていません。外部の道具に依存する設計なら、結果が届かない、時間切れになる、壊れた値が返るという失敗も入口の検査や呼出し側の例外処理に分けて試します。時間切れを0分に置き換えると本当の0分と区別できないため、失敗を表す方法を先に決めます。ここでは外部の道具を使用していないので、その動作を実測したとは扱いません。
表示だけの関数を直す
誤答では、変換した値を画面に出すことを返却と取り違えています。次のコードは実行できますが、返すべき組が呼出し側に届きません。
def show_time(total):
hours = total // 60
minutes = total % 60
print(hours, minutes)
result = show_time(125)
print(result)
期待した戻り値は (2, 5) ですが、実際の表示は 2 5 に続いて None です。関数内の print が最初の行を表示し、値を指定した return がないため、呼出し式の値は None になります。result には画面の文字ではなく、この None が入ります。
図3のように、原因は商や余りの計算ではなく、出口が表示だけになっていることです。図3の修正後は組を返し、呼出し側で必要に応じて表示します。

def show_time(total):
hours = total // 60
minutes = total % 60
return hours, minutes
result = show_time(125)
print(result)
Python 3.14.8で125を再実行すると、期待表示も実際の表示も (2, 5) です。画面への表示が1行になったことに加え、result が組を保持しているので、要素を取り出して次の計算にも使えます。0や60のような境界も再確認し、入口の条件を変えていないことを調べます。修正後の結果はそれぞれ (0, 0) と (1, 0) でした。
自分で受け渡しを追う5問
次の問題では、特記がなければ split_time は基本例題の定義を使います。入力は0以上の整数です。答えは指定された形で記してください。
- 展示の準備にかかった184分を変換します。戻り値をタプルで答え、元の分数に戻してください。
- 移動に59分と121分かかりました。それぞれの戻り値と合計180分の戻り値を、この順にタプルで答えてください。
a, b = split_time(246)を実行します。aとbの値を整数で答え、残りの分が条件内か確かめてください。checked_timeに-8、文字列"24"、Falseを渡します。それぞれ正常に返るか例外になるか、例外なら型名を順に答えてください。- 呼出し側で
result = show_time(95)を実行し、続けてprint(result)を実行します。表示だけを行う誤答版と、組を返す修正版について、画面に出る各行と変数resultに保存される値をそれぞれ答えてください。
答えと確かめ方
-
(3, 4)です。184を60で割ると商3、余り4です。3時間を分に戻して4分を加えると184分で、4は60未満です。Python 3.14.8で184を入力した実際の戻り値も(3, 4)でした。 -
順に
(0, 59)、(2, 1)、(3, 0)です。59分は1時間に届かず、121分は2時間と1分です。元の59と121を足すと180分になり、3時間に戻ります。同じ版で3回呼び出した結果もこの順でした。 -
aは4、bは6です。返った(4, 6)の先頭と次の要素がそれぞれ代入されます。4時間と6分は246分で、6は0以上60未満です。実際の値も4と6でした。 -
順に
ValueError、TypeError、TypeErrorです。負数は型の検査を通ってから範囲で拒否され、文字列と真偽値は型の検査で拒否されます。同じ版で各入力を個別に実行し、3つとも指定どおりの例外を確認しました。失敗が0分という正常値に化けていない点も確認できます。 -
誤答では画面に
1 35とNoneが順に表示され、resultはNoneです。修正後は(1, 35)が1行表示され、resultの値も(1, 35)です。95分は60分と35分に戻ります。同じ版で両方を実行し、表示と代入された値を別々に照合しました。
失敗を調べるときは、正しい値が出る場合と同じように、入力、期待する失敗、実際の結果を並べます。例えば負数での例外と文字列での例外は原因が異なります。両方を1つの「失敗」として数えると、型検査と範囲検査のどちらが働いたか見失います。
覚えておくこと
仮引数は関数内で受け取る名前、実引数は呼出し時に渡す値です。 return は呼出し元へ値を返し、print は画面へ表示します。 局所変数は関数内の名前であり、必要な値は出口から渡します。 入口の条件と失敗の扱いを決め、正常値と例外の双方を試します。
どこで取り違えたかを見分ける
呼出し側の変数に None が入る場合は、まず関数内の計算ではなく return の有無と位置を見ます。画面に表示された内容と、呼出し式の値を別々に書いてもらうと、両者を混ぜているか確かめられます。関数内の名前を呼出し側で使おうとした場合は、その名前が作られた範囲を図に戻って追います。
個別指導では、実引数を仮引数に対応させ、各代入の直後と返却直後の値を本人の言葉で説明できるかを確認します。次に0分、60分、前提外の入力を選び、期待値または期待する例外を先に書いてから実行します。入口と出口を言葉で定めれば、呼出し側は返された値を確かな形で利用できます。
読んで終わりにするか、ここから変えるか。
武蔵境駅徒歩30秒、講師1人に生徒1人の完全1対1。授業のあいだ、先生は隣を離れません。いまの詰まりを、無料相談でそのまま話してください。
まず15分だけ電話で話したい方は、無料電話相談(15分)から。塾からお電話を差し上げます。
本気になった日が、入塾の日。
お子様の教育、迷ったら「丸投げ」してください。必ず、期待以上の結果で返します。武蔵野で育む、武蔵境で学ぶ。
電話は年中無休。365日、24時間、お電話可能。



