Python
 Computer >> コンピューター >  >> プログラミング >> Python

Python関数の引数渡しの仕組みを解説!値渡しに見える理由とは

Pythonでは、関数に引数を渡すとき、その動作が「値渡し(pass by value)」なのか「参照渡し(pass by reference)」なのか迷うことがあります。結論から言うと、Pythonの引数渡しは「オブジェクトへの参照渡し(pass by object reference)」です。ただし、オブジェクトの種類によって挙動が異なるため、「値渡しのように見える」ケースがあります。

サンプルコードの出力結果

b = 30
a = ['10']

この出力を見ると、変数aの値は関数呼び出し後も変わっていないように見えます。そのため「Pythonの引数は値渡しだ」と結論づけたくなりますが、実態は少し異なります。

なぜ「値渡し」に見えるのか

ポイントは、イミュータブル(変更不可)なオブジェクトミュータブル(変更可能)なオブジェクトの違いです。

  • イミュータブルな型:整数(int)、文字列(str)、タプル(tuple)など。関数内で再代入しても、元の変数には影響しません。
  • ミュータブルな型:リスト(list)、辞書(dict)、セット(set)など。関数内で要素を変更すると、元のオブジェクトも変わります。

実際のコード例で確認する

まず、イミュータブルな整数の場合:

def change_value(x):
    x = 100  # ローカル変数xが新しいオブジェクトを指すだけ

num = 30
change_value(num)
print(num)  # 30 のまま(値渡しのように見える)

次に、ミュータブルなリストの場合:

def change_list(lst):
    lst.append('20')  # 元のオブジェクト自体を変更

my_list = ['10']
change_list(my_list)
print(my_list)  # ['10', '20'] に変わる(参照渡しのように見える)

まとめ

Pythonの引数には常にオブジェクトへの参照が渡されます。しかし、整数や文字列などのイミュータブルなオブジェクトは関数内で変更できないため、結果として「値渡し」のような振る舞いになります。一方、リストなどのミュータブルなオブジェクトは、関数内での変更が呼び出し元にも反映されます。

この仕組みを理解しておくと、「なぜ関数の中で書き換えたのに外の値が変わらないのか」「逆に意図せず書き換えられてしまうのか」といった疑問を防ぎ、より安全で予測しやすいコードを書けるようになります。

  1. Pythonのラムダ関数(lambda)とは?基本構文と使い方を実例付きで解説

    Pythonのラムダ関数(lambda関数)は、実行時にその場で生成される「名前を持たない匿名関数」です。通常、1行で記述され、特定の名前に束縛されることなく定義できます。 ラムダ関数には以下のような特徴があります。 関数の定義をその場で返すことができる return文を含まず、常に式(expression)を評価して結果を返す 関数オブジェクトが期待される場所なら、どこにでもラムダ式を記述できる ラムダ関数を使う場面 ある関数が一度しか使わず、呼び出し箇所も一箇所だけであるような場合、ラムダ関数が便利です。このようなケースでは、わざわざdef文で関数に名前を付けて定義する必要はありません

  2. Pythonで関数を引数として渡す方法をわかりやすく解説

    Pythonでは、関数もオブジェクトの一つとして扱われるため、他の関数の引数として渡すことができます。この仕組みを活用すると、柔軟で再利用性の高いコードを書くことができます。map()関数を使った例Pythonが標準で提供している代表的な例が、第一引数に関数を受け取る map() 関数です。map(function, iterable, ...) — iterable(イテラブル)の各要素に対してfunctionを適用し、その結果を返します。もちろん、独自に定義したカスタム関数でも、引数として関数を受け取るように実装できます。自作関数sqr(x)を引数として渡すここでは、リストの各要素を2乗す