Python二维数组复制异常:修改副本致其他副本同步变更
问题分析与解决
问题描述
尝试将二维数组r1复制到slot1、slot2、slot3三个变量中,期望修改slot1时不影响另外两个副本,但实际修改slot1后,slot2和slot3同步变化。已尝试copy.copy()和deepcopy()方法,但问题依旧。
原代码
import copy r1 = [4,10,12,5,11,6,3,16,21,25,13,19,14,22,24,7,23,20,18,15,0,8,1,17,2,9],[20,22,24,6,0,3,5,15,21,25,1,4,2,10,12,19,7,23,18,11,17,8,13,16,14,9],[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],[24],[0] r2 = [0,9,3,10,18,8,17,20,23,1,11,7,22,19,12,2,16,6,25,13,15,24,5,21,14,4],[0,9,15,2,25,22,17,11,5,1,3,10,14,19,24,20,16,6,4,13,7,23,12,8,21,18],[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],[12],[0] r3 = [1,3,5,7,9,11,2,15,17,19,23,21,25,13,24,4,8,22,6,0,10,12,20,18,16,14],[19,0,6,1,15,2,18,3,16,4,20,5,21,13,25,7,24,8,23,9,22,11,17,10,14,12],[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],[3],[0] r4 = [4,18,14,21,15,25,9,0,24,16,20,8,17,7,23,11,13,5,19,6,10,3,2,12,22,1],[7,25,22,21,0,17,19,13,11,6,20,15,23,16,2,4,9,12,1,18,10,3,24,14,8,5],[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],[17],[0] r5 = [21,25,1,17,6,8,19,24,20,15,18,3,13,7,11,23,0,22,12,9,16,14, 5,4,2,10],[16,2,24,11,23,22,4,13,5,19,25,14,18,12,21,9,20,3,10,6,8,0,17,15,7,1],[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],[7],[0] #empty slots for the rotors slot1 = [],[],[],[],[] slot2 = [],[],[],[],[] slot3 = [],[],[],[],[] class rotors: def set_rotors(self,s1,s2,s3): global slot1 global slot2 global slot3 slots=[s1,s2,s3] rotors=[r1,r2,r3,r4,r5] for sn in slots: slotn= copy.copy(rotors[sn-1]) if sn == s1: slot1 = slotn self.s1=sn if sn == s2: slot2=slotn self.s2=sn if sn == s3: slot3=slotn self.s3=sn def value(self, rotor): if rotor == 1: #return(alphabet[(slot1[2][signal]-slot1[4][0])%26]) return(slot1[0]) elif rotor == 2: #return(alphabet[(slot2[2][signal]-slot2[4][0])%26]) return(slot2[0]) elif rotor == 3: #return(alphabet[(slot3[2][signal]-slot3[4][0])%26]) return(slot3[0]) def ring_setting_down(self,slot,setting): if slot==1: for i in range(26): slot1[0][i] = (slot1[0][i] - setting)%26 for i in range(setting): slot1[1].insert(25,slot1[1].pop(0)) print("test 1") elif slot==2: for i in range(26): slot2[0][i] = (slot2[0][i] - setting)%26 for i in range(setting): slot2[1].insert(25,slot2[1].pop(0)) print("test 2") elif slot==3: for i in range(26): slot3[0][i] = (slot3[0][i] - setting)%26 for i in range(setting): slot3[1].insert(25,slot3[1].pop(0)) print("test 3") RT=rotors() RT.set_rotors(1,1,1) print(RT.value(1)) print(RT.value(2)) print(RT.value(3)) RT.ring_setting_down(1,1) print(RT.value(1)) print(RT.value(2)) print(RT.value(3))
预期输出
[4, 10, 12, 5, 11, 6, 3, 16, 21, 25, 13, 19, 14, 22, 24, 7, 23, 20, 18, 15, 0, 8, 1, 17, 2, 9] [4, 10, 12, 5, 11, 6, 3, 16, 21, 25, 13, 19, 14, 22, 24, 7, 23, 20, 18, 15, 0, 8, 1, 17, 2, 9] [4, 10, 12, 5, 11, 6, 3, 16, 21, 25, 13, 19, 14, 22, 24, 7, 23, 20, 18, 15, 0, 8, 1, 17, 2, 9] test 1 [3, 9, 11, 4, 10, 5, 2, 15, 20, 24, 12, 18, 13, 21, 23, 6, 22, 19, 17, 14, 25, 7, 0, 16, 1, 8] [4, 10, 12, 5, 11, 6, 3, 16, 21, 25, 13, 19, 14, 22, 24, 7, 23, 20, 18, 15, 0, 8, 1, 17, 2, 9] [4, 10, 12, 5, 11, 6, 3, 16, 21, 25, 13, 19, 14, 22, 24, 7, 23, 20, 18, 15, 0, 8, 1, 17, 2, 9]
实际输出
[4, 10, 12, 5, 11, 6, 3, 16, 21, 25, 13, 19, 14, 22, 24, 7, 23, 20, 18, 15, 0, 8, 1, 17, 2, 9] [4, 10, 12, 5, 11, 6, 3, 16, 21, 25, 13, 19, 14, 22, 24, 7, 23, 20, 18, 15, 0, 8, 1, 17, 2, 9] [4, 10, 12, 5, 11, 6, 3, 16, 21, 25, 13, 19, 14, 22, 24, 7, 23, 20, 18, 15, 0, 8, 1, 17, 2, 9] test 1 [3, 9, 11, 4, 10, 5, 2, 15, 20, 24, 12, 18, 13, 21, 23, 6, 22, 19, 17, 14, 25, 7, 0, 16, 1, 8] [3, 9, 11, 4, 10, 5, 2, 15, 20, 24, 12, 18, 13, 21, 23, 6, 22, 19, 17, 14, 25, 7, 0, 16, 1, 8] [3, 9, 11, 4, 10, 5, 2, 15, 20, 24, 12, 18, 13, 21, 23, 6, 22, 19, 17, 14, 25, 7, 0, 16, 1, 8]
原因分析
- r1的结构问题:
r1的定义是用逗号分隔的多个列表,实际是一个元组(Python中逗号分隔的序列默认是元组),元组内的元素是列表(可变对象)。 - 浅拷贝的局限性:原代码使用
copy.copy()做浅拷贝,仅复制了元组的外壳,元组内的列表并未被复制,只是引用了原r1中的列表对象。因此slot1、slot2、slot3指向的是同一组列表,修改其中一个就会影响所有引用。 - 循环逻辑冗余:当
s1、s2、s3取值相同时,循环会重复执行三次拷贝,且每次都会触发所有if条件,虽然不影响结果,但逻辑不够严谨。
解决方法
将copy.copy()替换为copy.deepcopy(),深拷贝会递归复制所有层级的对象,包括元组内的列表,确保每个slot都拥有独立的副本。同时优化循环逻辑,避免重复赋值。
修改后的代码
import copy r1 = [4,10,12,5,11,6,3,16,21,25,13,19,14,22,24,7,23,20,18,15,0,8,1,17,2,9],[20,22,24,6,0,3,5,15,21,25,1,4,2,10,12,19,7,23,18,11,17,8,13,16,14,9],[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],[24],[0] r2 = [0,9,3,10,18,8,17,20,23,1,11,7,22,19,12,2,16,6,25,13,15,24,5,21,14,4],[0,9,15,2,25,22,17,11,5,1,3,10,14,19,24,20,16,6,4,13,7,23,12,8,21,18],[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],[12],[0] r3 = [1,3,5,7,9,11,2,15,17,19,23,21,25,13,24,4,8,22,6,0,10,12,20,18,16,14],[19,0,6,1,15,2,18,3,16,4,20,5,21,13,25,7,24,8,23,9,22,11,17,10,14,12],[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],[3],[0] r4 = [4,18,14,21,15,25,9,0,24,16,20,8,17,7,23,11,13,5,19,6,10,3,2,12,22,1],[7,25,22,21,0,17,19,13,11,6,20,15,23,16,2,4,9,12,1,18,10,3,24,14,8,5],[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],[1
相关产品推荐
相关产品推荐

