らんだむな記憶

blogというものを体験してみようか!的なー

Python の関数コール (3)

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 の処理なので、関数のオブジェクトを作成する際に、デフォルト引数を抽出してオブジェクトにバインドしているものと思われる。