Pythonの関数は何渡し?
変数間における代入と同様に、Pythonの関数呼出し時に実引数として渡しているのはオブジェクトIDである。これはアドレスのような情報であるので、その点からするとC言語における参照渡し的な処理が行われることが予想される。しかし、代入時に行われる処理の違いから、単なる参照渡しとは事なる結果が得られることを示す。 code:val_ref1.py
def func(a): # (1)
a = -1 # (2)
x = 1 # (3)
print('before', x)
func(x) # (4)
print('after', x) # (5)
(3)において、インスタンス「1」を生成し、そのオブジェクトIDを変数 x に代入する。
(4)の関数呼び出しでは、変数xに格納されているオブジェクトIDを実引数として渡す。 (1)において、仮引数 a にインスタンス「1」のオブジェクトIDが代入され、関数の処理が始まる。
(2)において、新たなインスタンス「-1」を生成し、そのオブジェクトIDを変数aに代入する。
code:Figure.txt
func
└─ a:インスタンス「-1」のオブジェクトID
Global
└─ x:インスタンス「1」のオブジェクトID
その後、func関数が終了する。(5)において、変数xには(3)で代入されたオブジェクトIDが格納されたままになっているので、そちらが表示される。
これは、値渡し的な結果といえる。
次に、リストオブジェクトを渡し、部分的に上書きするような処理に修正する。
code:val_ref2.py
def func(a): # (1)
print('before', y)
func(y) # (3)
print('after', y)
(3)は、(0) で生成したリストインスタンスのオブジェクトIDを実引数として渡している。
(2)の代入文は、変数aが指すリストインスタンス中の添字で指定した要素の値の上書きを意味する。
結果として、リストインスタンスの値が書き換わるので、これは参照渡し的な結果が得られている。
code:Figure.txt
func
└─ a:(0) で生成したインスタンス「リスト0, 1, 2」のオブジェクトID 外部
└─ x:(0) で生成したインスタンス「リスト0, 1, 2」のオブジェクトID 誤解しないで欲しい例として、以下を示す。
code:val_ref3.py
def func(a):
print('before', z)
func(z)
print('after', z)
(1)のような代入を行うと、ローカル変数aの値は新たに生成されたリストインスタンスのオブジェクトIDで上書きされるので、(2)で生成したリストインスタンスには影響を与えない。
したがって、val_ref1.pyの場合と同じく値渡し的な処理が行われる。
code:Figure.txt
myfunc3
外部