• 你真的理解Python中del,remove,pop的用法吗?
  • 发布于 2个月前
  • 142 热度
    0 评论
  • 洪峰
  • 0 粉丝 17 篇博客
  •   
在 Python 中,有删除作用的一般是 del、remove 和 pop,相信很多人都用过,但是不是真的会有待商榷,下面我们先来看一个例子:
lst1 = [1,2,3,4]
lst2 = [1,2,3,4]
lst3 = [1,2,3,4]
lst4 = [1,2,3,4]

for i, j in enumerate(lst1):
   del j

for i, j in enumerate(lst2):
   lst2.remove(j)

for i, j in enumerate(lst3[:]):
   lst3.remove(j)

for i, j in enumerate(lst4):
   lst4.pop(i)

上述的代码运行完以后,你知道列表 lst1 ~ lst4 此时变成了什么吗?按照自己之前的理解,思考完毕以后请继续向下看:
>>> lst1
[1,2,3,4]
>>> lst2
[2,4]
>>> lst3
[]
>>> lst4
[2,4]

看了上面的结果,是不是觉的有点懵?为什么会输出 [2,4]?

很多人在用的时候就只是用,没有真正的去看到底用的原理是什么,就比如这里的「删除」,同样是叫「删除」就真的一样吗?所以在回答上面的疑问之前,我们先再看一下 del、remove 和 pop 的不同:

「del list_name」 这个删除只是从本地或者全局命名空间中删除了 list_name,这就是为什么在上述代码的操作中 lst1 前后没有改变;

「remove」是会删除第一个匹配到的指定值,而不是说特定的索引,如果没有找到指定值的话会抛出 ValueError 异常;

最后的「pop」则会删除指定索引处的元素并且返回它,如果指定的索引为无效索引则抛出 IndexError 异常。


看了上面对于三者「删除」之间的不同,然后我再来解释「为什么输出是 [2,4]」就很好理解了:

Python 中列表迭代是按照索引进行的,所以当我们从 lst2 或者 lst4 中删除索引为0,也就是元素 1 的时候,列表就变成了 [2,3,4],对于列表中剩下的 2、3、4 元素来说,它们的索引从 1、2、3 变成了 0、1、2。由于下一次迭代将获取索引为 1 的值,也就是 3,因此元素 2 将被彻底的跳过(类似的情况会交替发生在列表中的每个元素上)。

现在我们明白了问题所在,在最后我想再补充一点:在文章最初,代码中「在迭代时修改对象」是一种很 stupid 的做法,正确的做法应该是迭代对象的副本,如 lst3[:] 这种做法才是我们应该学习的正确做法,因为 Python 为切片列表创建了新的对象:
>>> lst1 = [1,2,3,4]
>>> id(lst1)
4301259848
>>> id(lst1[:])
4301260040

用户评论