参考図書
Python3エンジニア認定データ分析試験を受けてみました。
データ分析のモデルを動かしていくうえでの基礎となる知識を
体系的に学ぶことができました。とてもいい機会でした。
内容のなかの一部(とても一部)である代入と参照とコピーの違いについて
今回の試験で整理できたので、
その部分だけ自分なりに書いて残しておきます。
詳しい内容については教科書を参照ください。
- 教科書
Pythonによるあたらしいデータ分析の教科書(翔泳社) - 一般社団法人Pythonエンジニア育成推進協会のページ
公式サイト(データ分析試験)
代入と参照とコピー
Pythonの値はすべてオブジェクト。
変数は、オブジェクトを参照する「オブジェクトID」を保持して、変数から値(オブジェクト)を参照する。
a1 = aで代入する場合
変数aが保持しているオブジェクトIDが変数a1にも代入され、同じオブジェクトを参照(共有)する。
a = np.array([1, 2, 3])
a
## 出力結果
array([1, 2, 3])
a1 = a
a1
## 出力結果
array([1, 2, 3])
a1[1] = 5
a1
## 出力結果
array([1, 5, 3])
a
## 出力結果
array([1, 5, 3])
※a1 = a の代入で、変数aが保持しているオブジェクトIDが変数a1にも代入されるだけで、オブジェクトはコピーせずに共有するため、変数aが参照しているオブジェクト内容を変更したあと、変数a1が参照しているオブジェクト内容を表示すると変更された内容が表示される
copyメソッドでコピーする場合
a2 = a.copy()
a2
## 出力結果
array([1, 5, 3])
a2[0] = 6
a2
## 出力結果
array([6, 5, 3])
a
## 出力結果
array([1, 5, 3])
copyメソッドでコピーすると、a2をいじってもaの配列に反映されない
ravelは参照、flattenはコピー
c1 = np.array([0,1,2,3,4,5])
c2 = c1.reshape((2,3))
c2
## 出力結果
array([[0, 1, 2],
[3, 4, 5]])
c3,c4にそれぞれ別の値を上書きしてみる
c3 = c2.ravel()
c4 = c2.flatten()
c3[0] = 6
c4[1] = 7
## 出力結果
c3
## 出力結果
array([6, 1, 2, 3, 4, 5])
c4
## 出力結果
array([0, 7, 2, 3, 4, 5])
c2
## 出力結果
array([[6, 1, 2],
[3, 4, 5]])
※c2はc3の変更(ravel)の影響を受けているが、c4の変更(flatten)の影響は受けていない
→ravelは参照(つまり同じオブジェクトとして扱われる)
→flattenはコピーとなる
Pythonの標準のリストとNumpyのコピーは異なる
Python標準のリスト:浅いコピーと深いコピーを区別して扱う。
スライスは浅いコピーで、コピーした先の浅い層をいじってもコピー元には反映されない
py_list1 = [0,1]
py_list2 = py_list1[:]
py_list2[0] = 2
print(py_list1)
print(py_list2)
## 出力結果
[0, 1]
[2, 1]
Numpyでスライスを用いると同じオブジェクトを”参照”する
(a1 = aの挙動)
np_array1 = np.array([0,1])
np_array2 = np_array1[:]
np_array2[0] = 2
print(np_array1)
print(np_array2)
## 出力結果
[2 1]
[2 1]
おわり