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()でコピーを渡すのが安全
-
Pythonのラムダ関数(lambda)とは?基本構文と使い方を実例付きで解説
Pythonのラムダ関数(lambda関数)は、実行時にその場で生成される「名前を持たない匿名関数」です。通常、1行で記述され、特定の名前に束縛されることなく定義できます。 ラムダ関数には以下のような特徴があります。 関数の定義をその場で返すことができる return文を含まず、常に式(expression)を評価して結果を返す 関数オブジェクトが期待される場所なら、どこにでもラムダ式を記述できる ラムダ関数を使う場面 ある関数が一度しか使わず、呼び出し箇所も一箇所だけであるような場合、ラムダ関数が便利です。このようなケースでは、わざわざdef文で関数に名前を付けて定義する必要はありません
-
Pythonで関数を引数として渡す方法をわかりやすく解説
Pythonでは、関数もオブジェクトの一つとして扱われるため、他の関数の引数として渡すことができます。この仕組みを活用すると、柔軟で再利用性の高いコードを書くことができます。map()関数を使った例Pythonが標準で提供している代表的な例が、第一引数に関数を受け取る map() 関数です。map(function, iterable, ...) — iterable(イテラブル)の各要素に対してfunctionを適用し、その結果を返します。もちろん、独自に定義したカスタム関数でも、引数として関数を受け取るように実装できます。自作関数sqr(x)を引数として渡すここでは、リストの各要素を2乗す