以下两段代码:
listt=['a','b','a','b']
for i in listt:
if 'a'==i:
listt.remove(i)
print(listt)
运行结果为:
['b', 'b']
而对于
listt=['a','a','b','a','b']
for i in listt:
if 'a'==i:
listt.remove(i)
print(listt)
运行结果为['b', 'a', 'b']
注意:
for循环只决定是否进行内层的语句执行,并决定内层语句的循环次数;for语句只会按照列表元素的下标进行取数,下标会一直进行递增,不受是否删除或者增加元素的影响。
由于python中的list在元素删除或增加时,基于自动内存管理,会自动对内存进行收缩或者扩展,并对元素进行相应的移动,所以在进行元素删除操作时,要慎用for循环,以防存在删除不干净的情况
之所以存在上例问题,是由于remove在删除时,删除首次出现的元素,且python在删除元素之后,会进行元素的自动移位
[a,a,b,a,b]
第一次循环,for列表下标为0,取得i=a,执行内存语句,删除a,列表变为[a,b,a,b]
第二次循环,for列表下标为1,取得i=b,执行内存语句,内存语句不满足,进行下一次for循环
第三次循环,for列表下标为2,取得i=a,执行内存语句,remove删除第一个满足条件的元素,即删除第一个a,列表变为[b,a,b]
第四次循环,for列表下标为3,超出列表的现长度3([b,a,b]),结束for循环
执行外层print语句,输出最终结果[b,a,b]
可以通过以下两种方法解决:
1.【利用从尾部删除的方法实现】从尾部删除,将忽略删除元素的自动内存管理影响。
listt=['a','a','b','a','b']
for i in range(len(listt)-1,-1,-1): #range为前闭后开区间
if 'a'==listt[i]:
del listt[i]
print(listt)
2.【利用步长为1的切片器】
listt=['a','a','b','a','b']
for i in listt[::]: #切片操作不会因为下标越界而抛出异常,而是简单地在列表尾部截断或者返回一个空列表
if 'a'==i:
listt.remove(i)
print(listt)