浅いコピーと深いコピーの違い
ミュータブルなオブジェクトをコピーしたとき、そのオブジェクトの構造やコピーの仕方によっては挙動が大きく変わることがある。
単純にコピーはコピーじゃないんか?と思うけど一言にコピーと言っても同じではない。浅いコピーと深いコピーがある。
浅いコピー:Shallow Copy
深いコピー:Deep Copy
浅い深いってなんやねんって感じですけど、実際の挙動を見るのが早いですね。
例えば、以下のようなリストを代入したときと、浅いコピー、深いコピーしたときの挙動を見てみる。
import copy l = [0,1,[2,3]] l_assign = l l_copy = l.copy() l_deepcopy = copy.deepcopy(l) def print_l(): print('list:', l) print('assign:',l_assign) print('copy:',l_copy) print('deepcopy:',l_deepcopy) l[0] = 100 print_l() l[2][0] = 300 print_l()
まず最初の
l[0] = 100 print_l()
の出力を見ると
list: [100, 1, [2, 3]] assign: [100, 1, [2, 3]] copy: [0, 1, [2, 3]] deepcopy: [0, 1, [2, 3]]
となっていて、リスト本体と代入先は同様に変更されている。
コピーした方はどちらも変わっていない。
コピーした時点で基本的には別オブジェクトとなるからで、これだけだと浅い深いの違いはわからない。
違いが出るのは、ネストされたリスト側の操作をしたとき
つまり
l[2][0] = 300 print_l()
の出力なんだけど、
list: [100, 1, [300, 3]] assign: [100, 1, [300, 3]] copy: [0, 1, [300, 3]] deepcopy: [0, 1, [2, 3]]
こうなる。
浅いコピーの方にも同じ変更がされてしまっている。
つまり浅いコピーはオブジェクト中のオブジェクトはコピーされないっていうこと。
深いコピーをすれば、オブジェクト中のオブジェクトもコピーされて別オブジェクト扱いされるようになる。