Python|値渡しと参照渡しをわかりやすく解説

1. はじめに

Pythonを学ぶ上で、「値渡し」と「参照渡し」の違いは必ず理解しておきたい基本事項です。関数に引数を渡したとき、元の変数に影響があるのか、ないのか——これはバグの原因にもなりがちなポイントです。

本記事では、Pythonにおける「値渡し」と「参照渡し」の概念をわかりやすく解説し、実際のコード例とともに理解を深めていきます。初心者から中級者まで、「どうやって渡されるのか?」「どう影響するのか?」を丁寧に解説していきます。

 

2. Pythonにおける「値渡し」と「参照渡し」の基本

2-1. Pythonは値渡し? 参照渡し?

Pythonでは、厳密には「値渡し(pass by value)」でも「参照渡し(pass by reference)」でもなく、「オブジェクトの参照を値として渡す」という形式をとっています。これを「参照の値渡し(pass-by-object-reference)」とも呼びます。

2-2. イミュータブル型とミュータブル型

Pythonのオブジェクトには「変更できない型(イミュータブル)」と「変更できる型(ミュータブル)」があります。この違いが、関数に引数を渡すときの挙動に大きく影響します。

  • イミュータブル型: int, float, str, tuple など
  • ミュータブル型: list, dict, set など

2-3. 基本的なコード例

例:イミュータブル型(int)

def update_number(x):
    x = x + 10
    print("関数内のx:", x)

num = 5
update_number(num)
print("関数外のnum:", num)

実行結果:

関数内のx: 15  
関数外のnum: 5

解説:int型はイミュータブルなので、関数内で変更しても元の変数には影響がありません。

例:ミュータブル型(list)

def update_list(lst):
    lst.append(100)
    print("関数内のlst:", lst)

my_list = [1, 2, 3]
update_list(my_list)
print("関数外のmy_list:", my_list)

実行結果:

関数内のlst: [1, 2, 3, 100]  
関数外のmy_list: [1, 2, 3, 100]

解説:list型はミュータブルなので、関数内で変更すると元の変数にも影響します。

 

3. よくある使い方・応用例

3-1. 関数内でリストを安全に操作する方法

元のリストを変更せずに新しいリストを作るには、コピーを使います。

def safe_update_list(lst):
    new_lst = lst.copy()
    new_lst.append(999)
    print("コピー後のリスト:", new_lst)

original = [10, 20, 30]
safe_update_list(original)
print("元のリスト:", original)

実行結果:

コピー後のリスト: [10, 20, 30, 999]  
元のリスト: [10, 20, 30]

ポイント:関数内で元のリストを変更したくない場合は、copy()list()を活用しましょう。

3-2. ディクショナリ(dict)の参照渡し

辞書型もミュータブルなので、関数で直接更新されます。

def update_dict(d):
    d["new_key"] = "new_value"

my_dict = {"a": 1}
update_dict(my_dict)
print(my_dict)

実行結果:

{'a': 1, 'new_key': 'new_value'}

 

4. 注意点・エラー対策

4-1. 引数の影響を予期しないバグ

ミュータブル型を渡した場合、元のオブジェクトが書き換わる可能性があります。意図的でない変更はバグの原因になります。

4-2. ミュータブル型のデフォルト引数に注意

Pythonでは関数のデフォルト引数にミュータブル型を使うと予期しない挙動になります。

def add_item(item, lst=[]):
    lst.append(item)
    return lst

print(add_item(1))
print(add_item(2))  # 意図しない結果になる

実行結果:

[1]  
[1, 2]

対策:デフォルト値はNoneを使い、関数内で初期化する方法が安全です。

def add_item_safe(item, lst=None):
    if lst is None:
        lst = []
    lst.append(item)
    return lst

 

5. まとめ

  • Pythonの関数引数は「参照の値渡し」である
  • イミュータブル型は影響されず、ミュータブル型は変更が反映される
  • 予期せぬ動作を防ぐにはcopy()Noneの活用がポイント

実務でのポイント:データ加工やAPIレスポンスの処理などで、元データを壊さずに処理する技術として非常に重要です。

学習のコツ:まずはリストや辞書を関数に渡してみて、「何が起こるか」を実験することから始めましょう!

タイトルとURLをコピーしました