…は、(古典的な)deep copy じゃない。という話を、某 Python スレにて。
import copy a0 = [[1, 2, 3]] * 3 a1 = copy.deepcopy(a0) a0[0][0] = 'hoge' a1[0][0] = 'fuga' print a1 #=> [['hoge', 2, 3], ['hoge', 2, 3], ['hoge', 2, 3]] print a2 #=> [['fuga', 2, 3], ['fuga', 2, 3], ['fuga', 2, 3]]
もちろん Squeak システムの Smalltalk の deep copy は賢くない(笑)ので、
a1 a2 |
となります。
ちなみに、Python の deep copy の賢さは配列が再帰構造をとっているときに、さらによく分かるようになっています。
import copy a1 = [1, 2, 3] a1[0] = a1 a2 = copy.deepcopy(a1) a2[1] = 'hoge' print a2[0][1] #=> 'hoge' print a1[0][1] #=> 2
もちろん、Squeak システムの Smalltalk の deep copy は馬鹿なので、
a1 a2 |
となります。
もひとつちなみに、VisualWorks では Python と同じ結果になります。
全然関係ないのですが、ここで Ruby のリストにからめた二項演算子の振る舞いは Python にそっくりなことも分かりました。さらに上流もありそうです。ひまなときに辿ってみましょう。
#(1 2 3) * #(4 5 6) "=> #(4 10 18) " [1, 2, 3] * [4, 5, 6] #=> error #(1 2 3) * 3 "=> #(3 6 9) " Array streamContents: [: s | 3 timesRepeat: [s nextPutAll: #(1 2 3)]] "=> #(1, 2, 3, 1, 2, 3, 1, 2, 3) [1, 2, 3] * 3 #=> [1, 2, 3, 1, 2, 3, 1, 2, 3] #(1 2 3) + 3 "=> #(4 5 6)" [1, 2, 3] + 3 #=> error #(1 2 3) + #(4 5 6) "=> #(5 7 9) " #(1 2 3), #(4 5 6) "=> #(1 2 3 4 5 6) " [1, 2, 3] + [4, 5, 6] #=> [1, 2, 3, 4, 5, 6]