まずは下記の問題を御覧ください。
私はf(7)
を出力するのでは?と思いましたがそれは間違いです。
正解は6
を出力します。なぜでしょうか?
実はこれはデフォルト引数という仕組みで、引数を省略可能なのです。
呼び出しする度に値が再評価されることはないので、
ミュータブルなオブジェクトをデフォルト引数とすると、一見おかしな挙動を招きます。pythonにおける一種のバグです。
#順を追って解説
問題を再掲示します。
i = 5
i = 6
def f(arg = i):
i = 7
print(arg)
i = 8
i = 9
f()
注目するのは、3行目の「def f(arg=i):」で定義している「arg=i」。
引数「arg」に、値「i」を定義している。
次に注目するのは、1行目の「i = 6」。
3行目で関数を定義したとき、変数 i には値:6が格納されていた。
これによって、関数num()を定義した時、関数num()オブジェクトがキーワード引数 arg = i = 6 を保持することになる。
結果、関数実行時に引数を渡さなくてもエラーにはならないし、4行目でi = 7を定義しても関数実行時には arg = 6で実行される。
#ではどのように解釈して覚えるべきだろうか
・キーワード引数はイミュータブルである。そのため一度指定したdef f(arg = i):
は変更されないのだ。これは私の持論であるため鵜呑みにしないでほしい。
デフォルト値は、関数が定義された時点で、関数を 定義している 側のスコープ (scope) で評価されるのだ。
この記事は上記のチュートリアルを参考にしました。