Python の関数コール (2) - らんだむな記憶 の続き。
# -*- coding: utf-8 -*- import os def no_arg(): print("***** no_arg") def one_arg1(arg=[]): arg.append(1) return arg def one_arg2(arg=None): arg = arg or [] arg.append(1) return arg if __name__ == "__main__": os.system("ls") no_arg() one_arg1() print("***") one_arg2()
こんなスクリプト test.py
を用意するとして、まずは os.system
まで進めたいので、
(gdb) b Modules/posixmodule.c:4746 Breakpoint 1 at 0x191010: file ./Modules/posixmodule.c, line 4746. (gdb) r
して、ブレークしたらすかさず call_funtion
(Python/ceval.c:5060) と _PyFunction_Vectorcall
(Objects/call.c:353) にブレークポイントを置いてステップを進める。
(gdb) b Python/ceval.c:5060 Breakpoint 2 at 0x55eec6dfc496: Python/ceval.c:5060. (4 locations) (gdb) b Objects/call.c:353 Breakpoint 3 at 0x55eec6e11e36: file Objects/call.c, line 353. (gdb) c
これで後は関数呼び出しで何が起こっているか追いかけていくしかない。
たぶん https://github.com/python/cpython/blob/v3.9.3/Objects/call.c#L361 がデフォルト引数の取り出しではないだろうか。https://github.com/python/cpython/blob/v3.9.3/Objects/funcobject.c#L48 と併せるとそれっぽい気がする。
そして、恐らくデフォルト引数の設定は https://github.com/python/cpython/blob/v3.9.3/Python/ceval.c#L3617 と思われるが、これは MAKE_FUNCTION
の処理なので、関数のオブジェクトを作成する際に、デフォルト引数を抽出してオブジェクトにバインドしているものと思われる。