Pythonでは、関数やメソッドに引数を渡す際の取り扱いについて混乱を招くことがあります。特に、「値渡し」、「参照渡し」、「参照の値渡し」などの用語が使われると、それぞれの意味と違いを理解するのが難しくなります。
Pythonでは、すべての値はオブジェクトであり、変数にはオブジェクトのリファレンス(参照)が格納されています。関数が呼び出されると、実引数(呼び出し側の引数)のリファレンスが仮引数(関数側の引数)に”コピー”されて渡されます。この方式を「共有渡し」(call by sharing)あるいは「参照の値渡し」(call by value where value is the reference copy)と呼びます。
def func(arg):
arg += 10
num = 3
func(num)
print(num) # numの値は3のまま
上記の例では、関数func
の内部で引数arg
の値に10を加えています。しかし、関数を呼び出した後に、関数の外部で変数num
の値を表示してみると、関数の内部での引数の値の変更は反映されていません。これは、引数arg
に再代入することにより、引数arg
の参照先が変更されてしまったからです。
一方、ミュータブルな値(例えばリストや辞書)を引数として渡す場合には、関数内で参照先が変更されなければ、関数内での変更は呼び出し側に反映されます。
def func(arg):
arg.append(4)
lst = [1, 2, 3]
func(lst)
print(lst) # lstの値は[1, 2, 3, 4]
上記の例では、関数func
の内部でリストarg
に要素4を追加しています。関数を呼び出した後に、関数の外部でリストlst
の値を表示してみると、関数の内部での引数の値の変更が反映されています。これは、新たなオブジェクトは生成されず、リファレンスが変化しなかったためです。
以上のように、Pythonにおける引数の渡し方は、値渡しでも参照渡しでもなく、「参照の値渡し」であると理解することが重要です。これにより、関数やメソッドを呼び出す際に、引数がどのように振る舞うかを正確に予測することが可能になります。