Pythonにおける「参照渡し」の深淵:初心者にもわかりやすく解説
Pythonは、変数の挙動について少し複雑な面があります。特に、「参照渡し」と呼ばれる概念は、プログラミング初心者にとって理解の壁となりやすいものです。しかし、これを理解することで、Pythonのコードをより深く理解し、意図しないバグを回避できるようになります。
「参照渡し」って何?
まず、「参照」という言葉を理解しましょう。変数は、メモリ上の特定の場所(アドレス)を指し示す「ラベル」のようなものです。例えば、x = 10
というコードは、メモリ上のどこかに値 10
を格納し、変数 x
がその場所を指し示すようにします。
「参照渡し」とは、関数に引数を渡す際に、その値そのものではなく、その値が格納されているメモリ上の場所(参照)を渡すことを意味します。つまり、関数内で引数を変更すると、元の変数も影響を受ける可能性があるのです。
Pythonの変数の種類と参照渡し
Pythonには、大きく分けて以下の2種類のデータ型があります。
- 変更可能(mutable)なオブジェクト: リスト、辞書、集合など。
- 変更不可能(immutable)なオブジェクト: 数値(整数、浮動小数点数)、文字列、タプルなど。
この区別が、「参照渡し」の挙動を理解する上で非常に重要になります。
変更可能なオブジェクト(mutable)の場合
リストや辞書などの変更可能なオブジェクトを関数に渡した場合、参照が渡されます。つまり、関数内でリストや辞書の内容を変更すると、関数呼び出し元の変数も影響を受けます。
def modify_list(my_list):
my_list.append(4)
print("関数内:", my_list)
original_list = [1, 2, 3]
modify_list(original_list)
print("関数外:", original_list)
実行結果:
関数内: [1, 2, 3, 4]
関数外: [1, 2, 3, 4]
この例では、modify_list
関数内でリストに要素を追加した結果、関数呼び出し元の original_list
も変更されています。これは、original_list
と my_list
が同じメモリ上のリストを参照しているためです。
変更不可能なオブジェクト(immutable)の場合
整数、文字列、タプルなどの変更不可能なオブジェクトを関数に渡した場合も、参照が渡されます。しかし、関数内でこれらのオブジェクトを変更しようとすると、新しいオブジェクトが作成され、変数の参照先が変更されます。つまり、元の変数は影響を受けません。
def modify_number(x):
x = x + 1
print("関数内:", x)
original_number = 10
modify_number(original_number)
print("関数外:", original_number)
実行結果:
関数内: 11
関数外: 10
この例では、modify_number
関数内で x
に 1
を加算していますが、関数呼び出し元の original_number
は変更されていません。これは、x = x + 1
の行で、新しい整数オブジェクト 11
が作成され、x
がそのオブジェクトを参照するように変更されたためです。original_number
は依然として元の整数オブジェクト 10
を参照しています。
コピーと参照
もし、関数内でリストなどの変更可能なオブジェクトを変更しても、元の変数を変更したくない場合は、コピーを作成する必要があります。リストのコピーは、list()
関数やスライス [:]
を使用して作成できます。
def modify_list(my_list):
copied_list = my_list[:] # リストのコピーを作成
copied_list.append(4)
print("関数内:", copied_list)
original_list = [1, 2, 3]
modify_list(original_list)
print("関数外:", original_list)
実行結果:
関数内: [1, 2, 3, 4]
関数外: [1, 2, 3]
この例では、modify_list
関数内でリストのコピーを作成し、そのコピーを変更しています。そのため、関数呼び出し元の original_list
は変更されていません。
まとめ
Pythonにおける「参照渡し」は、変数の挙動を理解する上で重要な概念です。変更可能なオブジェクトと変更不可能なオブジェクトの違いを理解し、必要に応じてコピーを作成することで、意図しないバグを回避し、より洗練されたPythonコードを書けるようになります。最初は難しく感じるかもしれませんが、実際にコードを書いて試してみることで、徐々に理解が深まるはずです。
コラム一覧
◯for文
◯関数
◯配列
◯文字列
◯正規表現
◯ファイル入出力
◯openpyxl
◯Numpy
◯Matplotlib
◯Pandas
◯scikit-learn
◯seaborn
◯beautifulsoup
◯tkinter
◯OpenCV
◯pygame
◯メイン関数
◯自作ライブラリ
◯画像処理
◯機械学習
◯スクレイピング
◯データ分析
◯グラフ作成
◯API
◯可読性
◯デバッグ
◯例外処理
◯コメント
◯組み込み関数
◯flask
◯学び方
◯ビット演算
◯マルチスレッドプログラミング
◯参照渡し
◯pyenv
◯エディタ
◯生成AI
◯画像認識
◯Streamlit
◯lambda式
◯物理演算シミュレーション
◯命名規則
◯遺伝的アルゴリズム
◯関数型プログラミング
◯オブジェクト指向
◯ツリー図