Python デフォルト引数のワナ

変数を再代入してるのに、値が変わっていない!?

DIVE INTO EXAMで模擬テストをしていて分からなかったのがこのコード
結果は10です

i = 10  

def num(arg=i):  
    print(arg)  

i = 7  

num()  

num()で関数を呼び出す直前にi=7で再代入しているのに、なんで10なの???

デフォルト引数は関数の定義時にセットされて、再代入されない

Python♪引数のディフォルト値が変化する場合と変化しない場合の違い
Pythonのコードは上から順番に読み込まれるので、
上のコードだとdef num(arg=i):の時点でのiの値がデフォルト引数の値としてセットされるのか!
(そしてデフォルト引数はfinal変数)

iがリストだったら再代入できてしまう!?

デフォルト引数がリスト(mutable:変更可能オブジェクト)だと値が書き換えられる!
以下のコードを実行すると7が表示されます

i = [10] # iはリスト  

def num(arg=i):  
    print(arg[0]) # 最初の要素を表示  

i[0] = 7 # 最初の要素を変更  
# i = [7] だと結果は10のまま  

num()  

デフォルト引数は「(関数定義時に)代入された変数オブジェクトへのリンク」だから、
代入された変数オブジェクト自体に対してfinal変数扱い

リストはi[0]でリストiの最初の要素へのリンクとなっている
代入された変数オブジェクトがリストだと、リスト自体までがfinal変数(デフォルト引数)で
リストの要素はデフォルト引数には含まれていないのか