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

Python関数で引数を参照渡しする方法を徹底解説

Python関数で引数を参照渡しする方法

PythonにはC++のような明示的なポインタや参照渡しの構文はありませんが、実際には「オブジェクトへの参照」が引数として渡される仕組み(オブジェクト参照渡し)を採用しています。特にリストや辞書といったミュータブル(変更可能)なオブジェクトを関数に渡すと、関数内での変更が呼び出し元の変数にも反映されます。

サンプルコード

def modify_list(lst):
    lst.append('20')  # 関数内でリストを変更する

a = ['10']
modify_list(a)      # 変数aをそのまま渡す(参照が渡される)
b = ['10', '20']    # 比較用の独立したリスト

print('b =', b)
print('a =', a)

実行結果

b = ['10', '20']
a = ['10', '20']

解説

この実行結果は、変数aが参照渡しされたことを示しています。関数modify_list()の内部でlst.append('20')を実行すると、それは呼び出し元のリストaそのものへの操作になるため、メインスクリプト側のaの値も['10', '20']に更新されました。

これは、Pythonが変数そのものではなく「オブジェクトへの参照」を渡すためです。この動作は「call by object reference(オブジェクト参照渡し)」や「call by sharing」と呼ばれることがあります。

イミュータブルなオブジェクトの場合

一方、整数・文字列・タプルなどのイミュータブル(変更不可)なオブジェクトを渡した場合は、関数内で再代入しても呼び出し元には影響しません。再代入のタイミングで新しいオブジェクトが作成されるためです。

def change_number(num):
    num = 100  # 新しいオブジェクトを作るだけ

x = 10
change_number(x)
print(x)  # 出力: 10(変わらない)

参照渡しによる副作用を避ける方法

呼び出し元のリストを勝手に変更されたくない場合は、コピーを渡しましょう。

modify_list(a.copy())          # 浅いコピーを渡す

import copy
modify_list(copy.deepcopy(a))  # ネスト構造まで完全に複製

copy()による浅いコピー(shallow copy)では、ネストしたリストの内部要素までは複製されません。多次元リストなどを完全に独立させたい場合はcopy.deepcopy()を使用してください。

まとめ

  • Pythonの関数にはオブジェクトへの参照が渡される
  • リストや辞書などミュータブルなオブジェクトは、関数内での変更が呼び出し元に反映される(事実上の参照渡し)
  • 整数や文字列などイミュータブルなオブジェクトは、関数内での再代入が呼び出し元に影響しない
  • 副作用を避けたい場合はcopy()やdeepcopy()でコピーを渡すのが安全
  1. Pythonのラムダ関数(lambda)とは?基本構文と使い方を実例付きで解説

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

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

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