先来看下循环遍历删除list元素的一段代码:
L=[1,3,1,4,3,6,5] # 0 1 2 3 4 5 6(下标) for i in L: if i%2!=0:#%表示除商取余数,除以2余数为0,则表示为偶数,反之为奇数 L.remove(i)#若是奇数,则从list中剔除 print(L) 运行结果是: [1, 2, 4]
想一下,1是奇数,为什么没有被删除?
逐步来分析下,首先取第一元素i=1(下标为0),判断1%2!=0条件成立,所以剔除1,这时L变为L1=[1,1,2,3,4,5]。这时第二个1的下标变成0了,for循环已经取过下标0的元素了,所以后面取值时会跳过L1中的第一个元素1。so切记:循环list时不要删除list中的元素,否则会导致下标错位,结果异常。
如果你非要循环删除list中元素,可以定义两个一样的list,如下所示:
L=[1,1,1,2,3,4,5] # 0 1 2 3 4 5 6 L2=[1,1,1,2,3,4,5]#与L中元素下标一样 for i in L2:#从L2中循环,从L中删除元素 if i%2!=0: L.remove(i) print(L) 运行结果为: [2, 4]
#循环遍历过程中,L2列表一直未改变,只删除L中的元素,这样保证了每次循环时下标未变。
将上述代码中,分别定义了两个一样的list,如果改成L2=L,运行下面程序,你会发现结果还正确吗?
L=[1,1,1,2,3,4,5] # 0 1 2 3 4 5 6 # L2=[1,1,1,2,3,4,5] L2=L for i in L2: if i%2!=0: L.remove(i) print(L) 运行结果: [1, 2, 4]
可以看出,定义两个一样的list和L2=L,运行的结果不同,这就涉及到浅拷贝和深拷贝的概念。
定义的变量存储在内存中,实际上变量名存放的是内存地址,数据存放在另一块区域。从变量名找到存放数据的内存地址,就可以找到数据。
浅拷贝:L2=L或L2=L.copy(),这种方式,L2和L都指向同一块内存地址,所以L中元素被删除时,L2也是改变的。print(id())可打印内存地址
深拷贝:import copy这个模块,即L2=copy.deepcopy(L),L2和L的内存地址不一样,在内存中重新分配一个内存地址给L2.所以两个互不影响。