概要

Pythonでは、変数はオブジェクトへの参照が渡されますが、参照そのものは値渡しされます。これは、関数内でそのオブジェクト自体を操作できても、引数が参照するオブジェクトを再バインドすることはできないということです。このため、Pythonは厳密には「参照渡し」ではなく「オブジェクト参照の値渡し」と言われます。

可変オブジェクトの操作

リストや辞書のような可変オブジェクトは、関数に渡すとその中身を変更できます。次の例ではリストの内容を関数内で変更し、外部のリストにも反映されます。

def modify_list(my_list):
    my_list.append(4)
my_list = [1, 2, 3]
modify_list(my_list)
print(my_list)  # 出力: [1, 2, 3, 4]

ここでは、リストの内容が関数内で変更されると、関数外のリストにもその変更が反映されます。

不変オブジェクトの扱い

一方、整数や文字列のような不変オブジェクトは再バインドされるため、関数外の変数には影響しません。例えば、次のコードでは文字列の内容は変更されません。

def modify_string(s):
    s = "Changed"
s = "Original"
modify_string(s)
print(s)  # 出力: Original

これは、sが新しいオブジェクトに再バインドされているだけで、元のオブジェクトには影響がないためです。

参照渡しをシミュレートする方法

参照渡しを模倣したい場合、ラップするクラスやリストを使用して変更を追跡できます。例えば、リストに文字列をラップして渡すと、文字列のような不変オブジェクトでも参照を通して変更が反映されます。

def modify_wrapper(wrapper):
    wrapper[0] = "Changed"
wrapper = ["Original"]
modify_wrapper(wrapper)
print(wrapper[0])  # 出力: Changed

結論

Pythonでは、参照渡しのような動作を実現するには、可変オブジェクトを使用したり、オブジェクトをラップすることで対応できます。不変オブジェクトの場合は、変更が必要な場合に新しいオブジェクトを生成し、戻り値として返すのが一般的です。