在python中,我们有时希望删除列表中指定特征的元素,往往我们会使用pop()函数或remove()函数,而pop函数仅针对指定下标进行删除,remove函数可针对指定元素进行删除,因此一般使用remove函数。

以下面的代码为例:

我们希望删除指定列表中含有数字4(两位数即以4开头或结尾)的元素:

a=list(range(30,50))
print(a)
for i in a:
    if i%10==4 or i//10==4:
        a.remove(i)
print(a)

运行结果如下:

[30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
[30, 31, 32, 33, 35, 36, 37, 38, 39, 41, 43, 45, 47, 49]

仔细观察我们会发现,41,43,45,47,49 等数据并未被删除,为什么呢?

其实是for循环的机制捣的鬼,for循环的遍历本质上是对下标进行遍历,而由于列表实际上是可变的,因此数据对应的下标索引也会发生变化,当我们删除掉40整个数据时,41替代了原来40的下标位置,而for循环遍历到了40下标对应的下一个,故而跳过了41这个数据,从42开始删除,后面的几个数据也是同样的道理。

为了彻底删除,一种可行的办法时为列表创建一个副本用来遍历,然后对源列表进行删除操作

那么可以单纯创建新变量复制吗?答案是否定的。

a=list(range(100))
b=a
for i in b:
    if i%10==4 or i//10==4:
        a.remove(i)
print(a)

如上所示,b是a的复制,但是实质上仅仅是指向了a的内存,当a变化时b也会变化,因此是徒劳的。

解决方案是采用深度复制方法,以实现对源列表内容的完全复制,而不仅仅引用内存。

为此,还需要引用copy模块

完整代码如下:

from copy import deepcopy
print('for循环本质上是遍历列表的下标,而列表可变性因此索引也将发生变化,故而很可能发生无法删除干净的情况')
b=deepcopy(a)
for i in b:
    if(i%10==4 or i//10==4):
        a.remove(i)
print(id(a))
print(a)

至此,我们就解决了完全remove函数删除数据的'bug'。

这是第一篇博客,由于我的技术还非常浅薄,还有很多不足的地方,以后会创作更多的作品,感谢大家的观看!