ITと雑記とド田舎と

ド田舎在住エンジニアがIT備忘録と雑記を書くブログです

python3 値渡しと参照渡し

python3 覚え書きNo.5

 

pythonの変数への代入はすべて参照渡しです。でも、値渡しをしたい時ってありますよね。私がC言語からプログラミングに入ったからでしょうか。

la = [[1, 2, 3], [4, 5, 6]]
lb = la
print(lb)

lb[0][0] = 777
print(la)

実行結果
[[1, 2, 3], [4, 5, 6]]
[[777, 2, 3], [4, 5, 6]]

 このようにリストlbにリストlaを代入した後、lbの値を変更するとlaの値も変更されます。laとlbがメモリの同一領域を参照しているからです。

 これを防ぐためにはモジュールcopyのdeepcopy関数を利用します。

from copy import deepcopy

la = [[1, 2, 3], [4, 5, 6]]

lb = deepcopy(la)
la[0][0] = 777

print(la)
print(lb)

実行結果
[[777, 2, 3], [4, 5, 6]]
[[1, 2, 3], [4, 5, 6]]

今度はリストlaの値を変更しても、lbの値が変更されていません。iteratorも値渡し出来ました。

 

numpy配列の値渡し

また、numpyを利用している場合、numpyのcopy関数を利用できます。

import numpy as np

npla = np.array([[1, 2, 3], [4, 5, 6]])
nplb = npla.copy()

npla[0, 0] = 777
print(npla)
print(nplb)

実行結果
[[777   2   3]
 [  4   5   6]]
[[1 2 3]
 [4 5 6]]

 値渡しが出来ていることが分かります。

 

 ただし以下の場合のように、numpy配列の中にリストが入っているような形式だとcopy関数を利用しても中のリストは参照渡しになるようです。

import numpy as np

npla = np.array([[1, 2, 3], [4, 5]])
nplb = npla.copy()

npla[0][0] = 777
print(npla)
print(nplb)

実行結果
[list([777, 2, 3]) list([4, 5])]
[list([777, 2, 3]) list([4, 5])]