コラム

Pythonにおける「参照渡し」の深淵:初心者にもわかりやすく解説

Pythonは、変数の挙動について少し複雑な面があります。特に、「参照渡し」と呼ばれる概念は、プログラミング初心者にとって理解の壁となりやすいものです。しかし、これを理解することで、Pythonのコードをより深く理解し、意図しないバグを回避できるようになります。

「参照渡し」って何?

まず、「参照」という言葉を理解しましょう。変数は、メモリ上の特定の場所(アドレス)を指し示す「ラベル」のようなものです。例えば、x = 10 というコードは、メモリ上のどこかに値 10 を格納し、変数 x がその場所を指し示すようにします。

「参照渡し」とは、関数に引数を渡す際に、その値そのものではなく、その値が格納されているメモリ上の場所(参照)を渡すことを意味します。つまり、関数内で引数を変更すると、元の変数も影響を受ける可能性があるのです。

Pythonの変数の種類と参照渡し

Pythonには、大きく分けて以下の2種類のデータ型があります。

この区別が、「参照渡し」の挙動を理解する上で非常に重要になります。

変更可能なオブジェクト(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_listmy_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 関数内で x1 を加算していますが、関数呼び出し元の 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コードを書けるようになります。最初は難しく感じるかもしれませんが、実際にコードを書いて試してみることで、徐々に理解が深まるはずです。



< マルチスレッドプログラミング
pyenv >



コラム一覧

if文
for文
関数
配列
文字列
正規表現
ファイル入出力
openpyxl
Numpy
Matplotlib
Pandas
scikit-learn
seaborn
beautifulsoup
tkinter
OpenCV
pygame
メイン関数
自作ライブラリ
画像処理
機械学習
スクレイピング
データ分析
グラフ作成
API
可読性
デバッグ
例外処理
コメント
組み込み関数
flask
学び方
ビット演算
マルチスレッドプログラミング
参照渡し
pyenv
エディタ
生成AI
画像認識
Streamlit
lambda式
物理演算シミュレーション
命名規則
遺伝的アルゴリズム
関数型プログラミング
オブジェクト指向
ツリー図