一覧PG-06-1 · 関数の入出力

関数の引数と戻り値

在庫から要求個数を引く関数で、引数の式と受取先を確認します。続いて一覧の探索を使い、returnとbreakの後にどの処理が残るかを調べます。

説明

関数は呼び出すと本体を実行し、returnで呼出元へ値を返します。位置引数は並べた順に仮引数へ対応し、returnはループの中でも関数全体を終了します。

在庫から要求個数を引く関数で、引数の式と受取先を確認します。続いて一覧の探索を使い、returnとbreakの後にどの処理が残るかを調べます。

1関数を定義する

stockは在庫、requestedは要求個数を受け取る仮引数です。本体に到達したことも表示します。

def remaining(stock, requested):二つの仮引数 print("body", stock, requested)本体の実行記録 return stock - requested残数を呼出元へ返す

定義の時点ではbodyは出ません。仮引数へ渡す値が決まり、関数を呼んだ時に本体を実行します。

2引数の式を先に評価する

呼出元の変数から式を計算して渡します。

available = 10; order = 2呼出元の値; result = remaining(available, order + 1)式の結果を位置順に渡す; print("result", result, "caller", available, order)戻り値と呼出元の状態

order+1を先に評価して3を渡すため、関数内はstock=10、requested=3です。結果7を受け取り、呼出元のavailable=10とorder=2は変わりません。仮引数への整数の束縛は、呼出元の変数を直接書き換える処理ではありません。

3引数を逆にすると意味が変わる

同じ二値の渡す順序を逆にします。

print(remaining(2, 10)異なる位置へ同じ二値を渡す)

stock=2、requested=10なので-8です。型も文法も正しい呼出しですが、在庫10から2を引く意図とは異なります。位置だけで意味が分かりにくい場合は仮引数名を明確にします。

4実引数の評価順を記録する

引数として使う式が、どの順で計算されたか表示する関数を用意します。

def supplied(label, value):引数評価の観測用 print("argument", label)評価した式のラベル return value実引数となる値

次の呼出しではargumentの表示とbodyの表示を比較します。実引数の式の評価と、関数本体の実行は別の段階です。

5本体より先に両方の引数を評価する

二つの実引数を関数呼出しにします。

answer = remaining(supplied("stock", 10), supplied("requested", 2))左から引数を評価して本体へ; print(answer + 5)戻り値を次の式へ渡す

argument stock、argument requested、bodyの順で表示されます。戻り値8は後の+5で使われ、13になります。Pythonはここで実引数を左から右へ評価しています。

6ループ内でreturnする関数

商品一覧の先頭から、在庫が正の商品を探します。見つかればその場でreturnします。

def first_available(rows): for name, quantity in rows:商品を順に調べる print("visit", name) if quantity > 0: return name見つかった時点で関数終了 print("exhausted")最後まで調べた場合 return None該当商品なし

returnするとループだけでなく関数全体を抜けます。全て在庫なしの場合だけ、ループ後のexhaustedとreturn Noneへ進みます。

7見つかる場合と見つからない場合

二番目に在庫がある入力と、全て在庫0の入力を試します。

print("found", first_available([("pen", 0), ("book", 2), ("bag", 5)])途中で見つかる入力); print("found", first_available([("pen", 0)])見つからない入力)

最初はbookで返るためbagもexhaustedも表示されません。二回目は全件を調べてexhaustedが出て、Noneが返ります。

8breakにするとループ後も実行する

見つかった商品を変数へ保持し、breakでループだけを抜ける版を定義します。

def first_with_break(rows): found = None見つからない場合の値 for name, quantity in rows: if quantity > 0: found = name break値を残しループだけ終了 print("after loop")ループ後の処理 return found最後に呼出元へ返す

break後はafter loopを実行してからreturnします。ループ内のreturnへ置き換えると、この後処理も飛ばすことになるため、両者は単純な同義語ではありません。

9戻り値が同じでも実行経路が違う

同じ在庫一覧でbreak版を呼びます。

print("found", first_with_break([("pen", 0), ("book", 2), ("bag", 5)])同じ探索対象)

bookという戻り値は同じでも、after loopが実行されます。呼出しの確認では戻り値だけでなく、必要な後処理が通るかも調べます。

まとめ

実引数を評価してから位置順に仮引数へ渡し、戻り値を呼出元の式で使います。

breakはループ、returnは関数全体を終了します。

操作履歴と解説を振り返れます。

Python 3

1
def remaining(stock, requested): print("body", stock, requested) return stock - requested
2
available = 10; order = 2; result = remaining(available, order + 1); print("result", result, "caller", available, order)
body 10 3
result 7 caller 10 2
3
print(remaining(2, 10))
body 2 10
-8
4
def supplied(label, value): print("argument", label) return value
5
answer = remaining(supplied("stock", 10), supplied("requested", 2)); print(answer + 5)
argument stock
argument requested
body 10 2
13
6
def first_available(rows): for name, quantity in rows: print("visit", name) if quantity > 0: return name print("exhausted") return None
7
print("found", first_available([("pen", 0), ("book", 2), ("bag", 5)])); print("found", first_available([("pen", 0)]))
visit pen
visit book
found book
visit pen
exhausted
found None
8
def first_with_break(rows): found = None for name, quantity in rows: if quantity > 0: found = name break print("after loop") return found
9
print("found", first_with_break([("pen", 0), ("book", 2), ("bag", 5)]))
after loop
found book

演習完了