Pythonでは、関数を呼び出す際に引数を指定すると、参照渡しが使用されます。しかし、Pythonの場合、文字列や数値などのイミュータブルなオブジェクトと、リストや辞書などのミュータブルなオブジェクトでは挙動が異なります。
イミュータブルなオブジェクトの場合
イミュータブルなオブジェクト、つまり一度作成すると変更できないオブジェクトを引数に指定した場合、Pythonは参照の値渡しのように振る舞います。具体的には、以下のようなコードを考えてみましょう。
def update_complex(z):
print(f"in1)id of z:{id(z)}")
print(z)
z += 1j
print("z += 1j")
print(f"in2)id of z:{id(z)}")
print(z)
a = complex(1, 2)
print(f"out1)id of a:{id(a)}")
print(a)
update_complex(a)
print(f"out2)id of a:{id(a)}")
print(a)
このコードを実行すると、関数update_complexの中でz += 1jを実行した後、zのidが変わります。これは、イミュータブルなオブジェクトに対する変更操作が行われると、新しいオブジェクトが生成されるためです。
ミュータブルなオブジェクトの場合
一方、ミュータブルなオブジェクト、つまり作成した後でも変更できるオブジェクトを引数に指定した場合、Pythonは参照渡しを行います。具体的には、以下のようなコードを考えてみましょう。
def add_one(in_list):
print(f"in: {id(in_list)}")
in_list.append(1)
out_list = [1, 2, 3]
print(f"out: {id(out_list)}")
print(out_list)
add_one(out_list)
print(f"out: {id(out_list)}")
print(out_list)
このコードを実行すると、関数add_oneの中でin_list.append(1)を実行した後、out_listの内容が変わります。これは、ミュータブルなオブジェクトに対する変更操作がそのまま反映されるためです。
以上のように、Pythonの引数とポインタの挙動は、引数がイミュータブルなオブジェクトかミュータブルなオブジェクトかによって異なります。これを理解することで、Pythonのコードをより深く理解し、効率的なコードを書くことができます。.