関数の引数と戻り値
在庫から要求個数を引く関数で、引数の式と受取先を確認します。続いて一覧の探索を使い、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
def remaining(stock, requested):
print("body", stock, requested)
return stock - requestedavailable = 10; order = 2; result = remaining(available, order + 1); print("result", result, "caller", available, order)body 10 3 result 7 caller 10 2
print(remaining(2, 10))body 2 10 -8
def supplied(label, value):
print("argument", label)
return valueanswer = remaining(supplied("stock", 10), supplied("requested", 2)); print(answer + 5)argument stock argument requested body 10 2 13
def first_available(rows):
for name, quantity in rows:
print("visit", name)
if quantity > 0:
return name
print("exhausted")
return Noneprint("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
def first_with_break(rows):
found = None
for name, quantity in rows:
if quantity > 0:
found = name
break
print("after loop")
return foundprint("found", first_with_break([("pen", 0), ("book", 2), ("bag", 5)]))after loop found book
演習完了