ぴよまるの雑多な技術所

間違えて休職中ってずっと書いていて心配されていました。全部ちょっとずつ齧って好きって思える技術を見つけたい。研究分野は数理最適化。

Pythonで関数を呼び出す時に参照渡しで呼び出し元の変数を直接関数の中で書き換えたかった

Pythonで関数を呼び出す時の引数を参照渡しにして、呼び出し元の変数を直接関数の中で書き換えたかった時に躓きました。イミュータブルが良いとされている世の中ですが、どうしても参照している値のインデックスを呼び出し元の変数と直接関数の中とで共有したかったという状況です。この悩みの原因はそもそもPythonで関数を呼び出す時に参照渡しになっているところにあるのですが、同じように悩む人がいるかもしれないので詳細な仕組みについてまとめます。

参照渡しと値渡し

値渡しが引数の値をコピーして渡す方法で、独立してメモリ上に値を保管します。参照渡しがメモリアドレスを渡す方法で、呼び出し元と関数の中で同じ値を参照します。

Pythonのミュータブルとイミュータブル

ミュータブルな値はリスト、セット、ディクショナリなどです。部分的な値を変更が可能(メモリ上の値自体の変更が可能)です。 イミュータブルな値はタプル、数値型、文字列、ブーリアン、Noneなどです。注意するべきは、イミュータブルな値でも再代入は可能なことです。仕組みとしては、変数にメモリの番地が入っており、再代入するとメモリの番地が変更される、ということになります。一応コードで具体例を示します。

a = 5
b = a #この時点ではメモリの番地は同じ
b = 1 #ここでbのメモリの番地が変わる

Pythonは変数にメモリの番地を持っているため、値渡し参照渡しという切り口ではなく、ミュータブルイミュータブルと言う切り口で捉えるのが適切です。Pythonではメモリの番地を直接操作するような低レイヤの事柄は基本的に見えません。

ここまででわかるように、私が悩んだ

呼び出し元の変数を直接関数の中で書き換えたかった

Pythonではできないようです